HDU1698 线段树入门之区间修改/查询(lazy标记法)
2017-07-07 12:19
363 查看
Just a Hook
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 32434 Accepted Submission(s): 15927
Now Pudge wants to do some operations on the hook.
Let us number the consecutive metallic sticks of the hook from 1 to N. For each operation, Pudge can change the consecutive metallic sticks, numbered from X to Y, into cupreous sticks, silver sticks or golden sticks.
The total value of the hook is calculated as the sum of values of N metallic sticks. More precisely, the value for each kind of stick is calculated as follows:
For each cupreous stick, the value is 1.
For each silver stick, the value is 2.
For each golden stick, the value is 3.
Pudge wants to know the total value of the hook after performing the operations.
You may consider the original hook is made up of cupreous sticks.
Input The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 10 cases.
For each case, the first line contains an integer N, 1<=N<=100,000, which is the number of the sticks of Pudge’s meat hook and the second line contains an integer Q, 0<=Q<=100,000, which is the number of the operations.
Next Q lines, each line contains three integers X, Y, 1<=X<=Y<=N, Z, 1<=Z<=3, which defines an operation: change the sticks numbered from X to Y into the metal kind Z, where Z=1 represents the cupreous kind, Z=2 represents the silver kind and Z=3 represents the golden kind.
Output For each case, print a number in a line representing the total value of the hook after the operations. Use the format in the example.
Sample Input 1 10 2 1 5 2 5 9 3
Sample Output Case 1: The total value of the hook is 24.
Sourcghf 与前面几道显然的不同,前面几道都是对于某一个点的修改这个则是对一整段区间所有的元素都修改。 先回忆下为什么对一个点进行修时复杂度为logN,也就是树高,对于树上的结点对应的区间,其两个子节点中一定有一个包含这个待修改节点且另一个子节点不包含, 所以我们每次在每一层修改一个节点的值即可,树高~=logN所以修改了logN次。 查询时同理最多2*logN次(因为查找区间可能在两个子节点中都有重合部分) 对于区间修改如果还是这么来的话修改量可能会很大,比如对于[1,10]修改[1,10],则需要修改整棵树,计算量自然庞大。 于是引进了lazy标记的做法,股,顾名思义他不会及时的修改所有的点而是先记录下来,到需要查询时在释放。 pushdown()函数,即调整lazy标记函数,如果当前点存在lazy标记,我们对他进行调整,首先将标记传递给两个儿子并取消自身的标记,接着对于这个标记调整左右儿子的值。 在update()中使用的意义: 对于待修改节点,如果此节点区间完全包含于修改区间,显然以此节点为根的子树都需要修改,我们不这么做而是只修改这个节点的值并对其做上lazy标记 在查询时如果到了这个结点那么就释放标记给子节点,如果根本没访问过这个节点显然也不需要多此一举的释放标记。
含义就是对于一些反复进行的大区间的修改,我们只是修改了几次标记而已查询时顺路释放这样减少了很多更新时的操作从而降低了复杂度!
#include<bits/stdc++.h>
using namespace std;
#define lc (o<<1)
#define rc (o<<1|1)
#define mid ((L+R)>>1)
const int maxn=100000;
int Q[maxn<<2];
int laz[maxn<<2];
void build(int o,int L,int R)
{
if(L==R) {Q[o]=1;return;}
else{
build(lc,L,mid);
build(rc,mid+1,R);
Q[o]=Q[lc]+Q[rc];
}
}
void pushdown(int o,int L,int R)
{
if(laz[o]!=-1){
laz[lc]=laz[rc]=laz[o];
Q[lc]=laz[o]*(mid-L+1);
Q[rc]=laz[o]*(R-mid);
laz[o]=-1;
}
}
void update(int o,int L,int R,int l,int r,int v)
{
if(L>=l&&R<=r){
Q[o]=v*(R-L+1);
laz[o]=v;
return;
}
else{
pushdown(o,L,R);
if(l<=mid) {update(lc,L,mid,l,r,v);}
if(r>mid) {update(rc,mid+1,R,l,r,v);}
}
Q[o]=Q[lc]+Q[rc];
}
int query(int o,int L,int R,int l,int r)
{
if(L>=l&&R<=r) return Q[o];
pushdown(o,L,R);
if(r<=mid) return query(lc,L,mid,l,r);
else if(l>mid) return query(rc,mid+1,R,l,r);
else return query(lc,L,mid,l,r)+query(rc,mid+1,R,l,r);
}
int main()
{
int n,m,i,j,k=0,t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
int q;
memset(laz,-1,sizeof(laz));
build(1,1,n);
scanf("%d",&q);
while(q--){
int a,b,c,z;
scanf("%d%d%d",&a,&b,&c);
update(1,1,n,a,b,c);
}
printf("Case %d: The total value of the hook is %d.\n",++k,Q[1]);
}
return 0;
}
相关文章推荐
- HDU 1698 Just a Hook【线段树】区间修改,查询总和
- (HDU 1754)I Hate It 线段树区间查询入门,单点修改
- HDU-1166 敌兵布阵 (线段树 入门题 点修改 区间查询)
- HDU-1754 I Hate It (线段树 入门题 点修改 区间查询)
- HDU-1698-Just A Hook (线段树区间修改,区间查询)
- HDU 1698 Just a Hook (线段树:区间修改+区间查询)
- HDU 1698 Just a Hook(线段树-区间修改|区间查询)
- 【线段树I:点修改+区间查询】hdu 1754 I Hate It
- HDU 1698——Just a Hook(线段树,区间修改)
- hdu 4819 二维线段树,单点修改区间查询
- HDU 1698 Just a Hook (线段树区间修改)
- hdu 1698 线段树(区间成段修改)
- hdu 1754 I Hate It【线段树】 区间修改,最值查询
- hdu-1698-Just a Hook(线段树-区间修改模版)
- hdu 1698 线段树区间修改
- 线段树区间修改 HDU 1698
- HDU 1166 敌兵布阵 (线段树单点更新+区间查询入门)
- 树套树:二维线段树初步:hdu1823——Luck and Love(单点修改,区间查询)
- HDU 1698 Just a Hook (线段树区间修改)
- HDU - 1698 Just a Hook (线段树区间修改)