HDU 4578 Transformation --线段树,好题
题意: 给一个序列,初始全为0,然后有4种操作:
1. 给区间[L,R]所有值+c
2.给区间[L,R]所有值乘c
3.设置区间[L,R]所有值为c
4.查询[L,R]的p次方和(1<=p<=3)
解法: 线段树,维护三个标记,addmark,mulmark,setmark分别表示3种更新,然后p[1],p[2],p[3]分别表示该节点的1,2,3次方和。标记传递顺序setmark一定是第一个,因为setmark可以使mulmark,addmark都失效还原,mulmark和addmark的顺序倒是无所谓。
这题写了半个比赛时间,写的很迷,还是没写出来, 后来看了别人写的,才知道自己很多地方都没更新好甚至没更新。这题算是一道线段树的综合题了,混合了几种常见的更新,对线段树的整体把握很有帮助。
比如:
1.如果setmark有值,那么addmark,mulmark全部要还原。
2.如果mulmark有值,那么addmark也要更新,更新为addmark*mulmark
就是这两点一直没考虑到,WA了好久。
在addmark下传过程中更新p[1],p[2],p[3]的方法如下:
比如 a^3 -> (a+c)^3 的过程: (a+c)^3 = a^3 + c^3 + 3a*c^2 + 3*a^2*c, a是变量, 所以提取出c,那么p[3]可以由p[1],p[2]推出,p[2]可以由p[1]推出。
即 p[3] = p[3] + c^3 + 3*c^2*p[1] + 3*c*p[2] .
p[2]同理可以由p[1]推出。
然后每次都做一下pushdown,就可以得出正确答案。
当时像优化一下,少做几次pushdown,即这次的操作类型与上次一样就不pushdown,结果那样就会出现问题,还不如每次都pushdown呢。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define Mod 10007
#define SMod 10007
using namespace std;
#define N 100017 struct node{
int p[];
int setmark,addmark,mulmark;
}tree[*N]; void pushup(int rt){
for(int i=;i<=;i++) tree[rt].p[i] = (tree[*rt].p[i] + tree[*rt+].p[i])%SMod;
} void pushdown(int l,int r,int rt)
{
int mid = (l+r)/;
if(tree[rt].setmark)
{
int mk = tree[rt].setmark;
tree[rt<<].setmark = tree[rt<<|].setmark = mk;
tree[rt<<].addmark = tree[rt<<|].addmark = ;
tree[rt<<].mulmark = tree[rt<<|].mulmark = ; tree[rt<<].p[] = (mid-l+)%Mod*mk%SMod;
tree[rt<<|].p[] = (r-mid)%Mod*mk%SMod; tree[rt<<].p[] = (mid-l+)%Mod*mk%SMod*mk%SMod;
tree[rt<<|].p[] = (r-mid)%Mod*mk%SMod*mk%SMod; tree[rt<<].p[] = (mid-l+)%Mod*mk%SMod*mk%SMod*mk%SMod;
tree[rt<<|].p[] = (r-mid)%Mod*mk%SMod*mk%SMod*mk%SMod;
tree[rt].setmark = ;
}
if(tree[rt].mulmark != )
{
int mk = tree[rt].mulmark;
tree[rt<<].mulmark *= mk, tree[rt<<].mulmark%=SMod;
tree[rt<<|].mulmark *= mk, tree[rt<<|].mulmark%=SMod; tree[rt<<].addmark = tree[rt<<].addmark%SMod*mk%SMod;
tree[rt<<|].addmark = tree[rt<<|].addmark%SMod*mk%SMod; tree[rt<<].p[] = tree[rt<<].p[]%Mod*mk%SMod;
tree[rt<<|].p[] = tree[rt<<|].p[]%Mod*mk%SMod; tree[rt<<].p[] = tree[rt<<].p[]%Mod*mk%SMod*mk%SMod;
tree[rt<<|].p[] = tree[rt<<|].p[]%Mod*mk%SMod*mk%SMod; tree[rt<<].p[] = tree[rt<<].p[]%Mod*mk%SMod*mk%SMod*mk%SMod;
tree[rt<<|].p[] = tree[rt<<|].p[]%Mod*mk%SMod*mk%SMod*mk%SMod;
tree[rt].mulmark = ;
}
if(tree[rt].addmark)
{
int mk = tree[rt].addmark;
tree[rt<<].addmark += mk, tree[rt<<].addmark%SMod;
tree[rt<<|].addmark += mk, tree[rt<<|].addmark%SMod; tree[rt<<].p[] = (tree[rt<<].p[]%Mod + (mid-l+)%Mod*mk%SMod*mk%SMod*mk%SMod + *mk%Mod*tree[rt<<].p[]%SMod + *mk%SMod*mk%SMod*tree[rt<<].p[]%SMod)%SMod;
tree[rt<<|].p[] = (tree[rt<<|].p[]%Mod + (r-mid)%Mod*mk%SMod*mk%SMod*mk%SMod + *mk%Mod*tree[rt<<|].p[]%SMod + *mk%SMod*mk%SMod*tree[rt<<|].p[]%SMod)%SMod; tree[rt<<].p[] = (tree[rt<<].p[]%Mod + (mid-l+)%Mod*mk%SMod*mk%SMod + *mk%Mod*tree[rt<<].p[]%SMod)%SMod;
tree[rt<<|].p[] = (tree[rt<<|].p[]%Mod + (r-mid)%Mod*mk%SMod*mk%SMod + *mk%Mod*tree[rt<<|].p[]%SMod)%SMod; tree[rt<<].p[] = (tree[rt<<].p[]%Mod + (mid-l+)%Mod*mk%SMod)%SMod;
tree[rt<<|].p[] = (tree[rt<<|].p[]%Mod + (r-mid)%Mod*mk%SMod)%SMod;
tree[rt].addmark = ;
}
} void build(int l,int r,int rt)
{
tree[rt].setmark = tree[rt].addmark = ;
tree[rt].mulmark = ;
memset(tree[rt].p,,sizeof(tree[rt].p));
if(l == r) return;
int mid = (l+r)/;
build(l,mid,rt<<);
build(mid+,r,rt<<|);
} void update(int l,int r,int aa,int bb,int tag,int val,int rt) //tag = 3 : set 2:mul 1: add
{
if(aa <= l && bb >= r)
{
if(tag == )
{
tree[rt].p[] = (r-l+)%Mod*val%SMod;
tree[rt].p[] = (r-l+)%Mod*val%SMod*val%SMod;
tree[rt].p[] = (r-l+)%Mod*val%SMod*val%SMod*val%SMod;
tree[rt].setmark = val;
tree[rt].addmark = ;
tree[rt].mulmark = ;
}
else if(tag == )
{
tree[rt].p[] = tree[rt].p[]%SMod*val%SMod;
tree[rt].p[] = tree[rt].p[]%SMod*val%SMod*val%SMod;
tree[rt].p[] = tree[rt].p[]%SMod*val%SMod*val%SMod*val%SMod;
tree[rt].mulmark = tree[rt].mulmark%SMod*val%SMod;
tree[rt].addmark = tree[rt].addmark%SMod*val%SMod;
}
else if(tag == )
{
tree[rt].p[] = (tree[rt].p[]%SMod + (r-l+)%SMod*val%SMod*val%SMod*val%SMod + *val%SMod*tree[rt].p[]%SMod + *val%SMod*val%SMod*tree[rt].p[]%SMod)%SMod;
tree[rt].p[] = (tree[rt].p[]%SMod + (r-l+)%SMod*val%SMod*val%SMod + *val%SMod*tree[rt].p[]%SMod)%SMod;
tree[rt].p[] = (tree[rt].p[]%SMod + (r-l+)%SMod*val%SMod)%SMod;
tree[rt].addmark = (tree[rt].addmark+val)%SMod;
}
return;
}
int mid = (l+r)/;
pushdown(l,r,rt);
if(aa <= mid) update(l,mid,aa,bb,tag,val,rt<<);
if(bb > mid) update(mid+,r,aa,bb,tag,val,rt<<|);
pushup(rt);
} int query(int l,int r,int aa,int bb,int i,int rt)
{
if(aa > r || bb < l) return ;
if(aa <= l && bb >= r)
return tree[rt].p[i];
pushdown(l,r,rt);
int res = ;
int mid = (l+r)/;
return (query(l,mid,aa,bb,i,rt<<)%SMod+query(mid+,r,aa,bb,i,rt<<|)%SMod)%SMod;
} int main()
{
int n,m,i,j,op,x,y,c;
while(scanf("%d%d",&n,&m)!=EOF && n+m)
{
build(,n,);
while(m--)
{
scanf("%d%d%d%d",&op,&x,&y,&c);
if(op != ) update(,n,x,y,op,c,);
else printf("%d\n",query(,n,x,y,c,)%SMod);
}
}
return ;
}
HDU 4578 Transformation --线段树,好题的更多相关文章
- hdu 4578 Transformation 线段树多种操作裸题
自己写了一个带结构体的WA了7.8次 但是测了几组小数据都对..感觉问题应该出在模运算那里.写完这波题解去对拍一下. 以后线段树绝不写struct!一般的struct都带上l,r 但是一条线段的长度确 ...
- hdu 4578 Transformation 线段树
没什么说的裸线段树,注意细节就好了!!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> ...
- Transformation HDU - 4578(线段树——懒惰标记的妙用)
Yuanfang is puzzled with the question below: There are n integers, a 1, a 2, …, a n. The initial val ...
- Transformation 线段树好题 好题 (独立写出来对线段树不容易)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)T ...
- HDU 4747 Mex ( 线段树好题 + 思路 )
参考:http://www.cnblogs.com/oyking/p/3323306.html 相当不错的思路,膜拜之~ 个人理解改日补充. #include <cstdio> #incl ...
- hdu 1754 I Hate It 线段树基础题
Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求, ...
- hdu 1754 I Hate It(线段树水题)
>>点击进入原题测试<< 思路:线段树水题,可以手敲 #include<string> #include<iostream> #include<a ...
- HDU 1698 Just a Hook (线段树模板题-区间求和)
Just a Hook In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of t ...
- [AHOI 2009] 维护序列(线段树模板题)
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小 ...
随机推荐
- Matter.js – 你不能错过的 2D 物理引擎
Matter.js 是一个 JavaScript 2D 刚体物理引擎的网页.Matter.Engine 模块包含用于创建和操作引擎的方法.这个引擎是一个管理更新和渲染世界的模拟控制器. Matter. ...
- Icon Font浅谈
这周继续在弄hybird app 的 UI框架的重构,进行到了编写换肤功能的阶段,而在做换肤之前,我想应该先弄一套框架内置的图标. 而图标无非就是两种做法: 1.图片 使用图片很正常,但是有缺陷的. ...
- AloneJs —— 简洁高效的JavaScript UI库
以前做项目时用了一些第三方的JS UI库,项目比较low的时候用还行,一旦项目要求比较高,特别是交互比较复杂时,某些第三方UI库就显得无能为力,用起来也不顺手,改也不好改,所以我就自己基于jQuery ...
- JavaScript学习03 JS函数
JavaScript学习03 JS函数 函数就是包裹在花括号中的代码块,前面使用了关键词function: function functionName() { 这里是要执行的代码 } 函数参数 函数的 ...
- Provisioning Profile文件在哪找?
~/Library/MobileDevice/Provisioning Profiles
- Linux下怎么查看当前系统的版本
Linux下怎么查看当前系统的版本: uname -r 功能说明:uname用来获取电脑和操作系统的相关信息. 语 法:uname [-amnrsvpio][--help][--version] ...
- JAVA中获取路径
内容来自于snannan_268 关键字: java中获取路径 JAVA中获取路径: 1.jsp中取得路径: 以工程名为TEST为例: (1)得到包含工程名的当前页面全路径:request.get ...
- CMPP错误码说明
与中国移动代码的对应关系. MI::zzzzSMSC返回状态报告的状态值为EXPIREDMJ:zzzzSMSC返回状态报告的状态值为DELETEDMK:zzzzSMSC返回状态报告的状态值为UNDEL ...
- JavaScript Patterns 6.5 Inheritance by Copying Properties
Shallow copy pattern function extend(parent, child) { var i; child = child || {}; for (i in parent) ...
- C#中去掉表中重复的数据
/// <summary> /// 去掉表中重复的数据 int /// </summary> /// <param name="SourceTable&quo ...