您的位置:首页 > 其它

线段树(二)区间更新

2015-08-10 14:55 417 查看
hdu 1698

调试了很久,没想到一次ac了。

注意:区间更新中用到一种技术,延迟更新pushdown(v)。如果不使用延迟更新,而一个个的更新,长度为n的区间更新需要nlogn,而数组直接更新只需要n。体现不出线段树的优势,容易超时。

需要注意的另一点,建树的时候所有节点的状态都要考虑好,由于我做这题时,没有考虑好内节点的状态,导致样例跑出23的结果。这发代码可以当做模板来用。

区间更新线段树通常会出现一个段内的值(颜色等)不同的情况,需要进行标记清楚。

付ac代码:

#include<iostream>

#include<fstream>

#include<set>

#include<stack>

#include<cmath>

#include<cstring>

#include<cstdio>

#include<queue>

#include<algorithm>

using namespace std;

typedef long long LL;

const int MAX=0xfffffff;

const int mx=110000;

struct node{

int l,r,col;

}tree[mx*4];

void pushdown(int v)

{

if(tree[v].col!=-1)

{

tree[v*2].col=tree[v*2+1].col=tree[v].col;

tree[v].col=-1;

}

}

void build(int v,int l,int r)

{

tree[v].l=l,tree[v].r=r,tree[v].col=1;

if(l==r)

{

return;

}

int mid=(l+r)/2;build(v*2,l,mid),build(v*2+1,mid+1,r);

}

void update(int v,int l,int r,int col)

{

if(tree[v].col==col) return;

if(tree[v].l==l&&tree[v].r==r)

{

tree[v].col=col;

return ;

}

pushdown(v);

int mid=(tree[v].l+tree[v].r)/2;

if(l>mid) update(v*2+1,l,r,col);

else if(r<=mid) update(v*2,l,r,col);

else

{

update(v*2,l,mid,col);

update(v*2+1,mid+1,r,col);

}

}

int ans;

void query(int v,int l,int r)

{

if(tree[v].l==l&&tree[v].r==r&&tree[v].col!=-1)

{

ans+=(tree[v].col)*(tree[v].r-tree[v].l+1);

return ;

}

pushdown(v);

int mid=(tree[v].l+tree[v].r)/2;

if(l>mid) query(v*2+1,l,r);

else if(r<=mid) query(v*2,l,r);

else

{

query(v*2,l,mid);

query(v*2+1,mid+1,r);

}

}

int main( )

{

//freopen("in.txt","r",stdin);

int t;

scanf("%d",&t);

for(int ca=1;ca<=t;ca++)

{

int n,q;

scanf("%d%d",&n,&q);

build(1,1,n);

for(int i=1;i<=q;i++)

{

int x,y,z;

scanf("%d %d %d",&x,&y,&z);

update(1,x,y,z);

}

ans=0;

query(1,1,n);

printf("Case %d: The total value of the hook is %d.\n",ca,ans);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: