HDU 5023线段树区间染色,统计区间内颜色个数
这个也是一个线段树的模板
#include<iostream> #include<string.h> #include<algorithm> #include<stdio.h> #include<set> using namespace std; const int maxx = 1000050; set<int>s; struct node{ int color; int left; int right; int mid; }a[maxx<<2]; void pushdown(int root){ if(a[root].color){//把修改到两个子节点,并重新把laze清空 a[root<<1].color=a[root].color; a[root<<1|1].color=a[root].color; a[root].color=0; } } void buildtree(int root,int l,int r) { int mid=(l+r)>>1; a[root].left=l; a[root].right=r; a[root].mid=mid; a[root].color=2; if(l==r)return; buildtree(root*2,l,mid); buildtree(root*2+1,mid+1,r); } void update(int root,int l,int r,int c){ if (a[root].left == l && a[root].right == r){ a[root].color=c;//满足延时标记所满足的区间 return; } if (a[root].color==c)return; pushdown(root);//所更新的区间比较小,我们可以把修改push下去 if(l>a[root].mid)update(root<<1|1,l,r,c);//所求区间在现在的区间的右边,所以选择当前节点的右儿子 else if (r<=a[root].mid)update(root<<1,l,r,c);//在左边,选择左儿子 else {//通过中间节点进行二分 update(root<<1,l,a[root].mid,c); update(root<<1|1,a[root].mid+1,r,c); } } void query(int root,int l,int r){ if (a[root].color){//当前的laze标记已经标记到这个位置 s.insert(a[root].color); return; } //如果没有到这个位置代表需要往下找 同理 if (l > a[root].mid)query(root<<1|1,l,r); else if (r<=a[root].mid)query(root<<1,l,r); else{ query(root<<1,l,a[root].mid); query(root<<1|1,a[root].mid+1,r); } } int main(){ int n,m; int l,r,c; char op[10]; while(~scanf("%d%d",&n,&m) &&(n+m)){ buildtree(1,1,n); for (int i=0;i<m;i++){ scanf("%s%d%d",op,&l,&r); if(op[0]=='P'){ scanf("%d",&c); update(1,l,r,c); }else{ s.clear(); query(1,l,r); int ss=s.size(); set<int>::iterator it; for (it=s.begin();it!=s.end();it++){ printf("%d",*it); if (ss>1)printf(" "); ss--; } printf("\n"); } } } return 0; }
题,只需要添加laze标记,并且在不断的维护中,保存更新并pushdown下去,然后为了避免重复,搞一个set就行。
有不懂欢迎咨询
QQ:1326487164(添加时记得备注)