poj 2777 线段树+延迟更新
题意:板块涂色,询问区间内颜色的数目。
解题:因为题目给出颜色数目最多30种,因此可以借用二进制中的或运算 来更新父区间。 但是这写的是线段树常用的懒人标记------延迟更新。
别人已经写的很好了,直接借用吧,博客链接 https://blog.csdn.net/Tong_zhi/article/details/82683219
言下之意就是 当遇到的区间,已经被包含 在更新区间内, 如果按照常规的思路,那么就是继续遍历到叶结点,一一进行修改,但是这样很浪费时间。
这里借用了懒标记,也就是对这种 纯区间(区间内的元素都需要更改成某值),我们只需要对他加一个标记。当下次更新或者询问的时候再进行修改。
修改操作: 先将自己的标记赋值给左右儿子,然后取消自己的标记,对于左右儿子的标记,也一样当下次更新或者询问的时候再进行修改。
下推操作(懒标记):
void pushdown(int rt) { if (tree[rt].lazy){ tree[rt<<1].col=tree[rt<<1|1].col=tree[rt].lazy; tree[rt<<1].lazy=tree[rt<<1|1].lazy=tree[rt].lazy; tree[rt].lazy=0; } return ; }
AC代码:
#include<iostream> #include<cstdio> #include<ctime> #include<cstring> #include<cstdlib> #include<cmath> #include<queue> #include<stack> #include<map> #include<algorithm> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #define Mem0(x) memset(x,0,sizeof(x)) #define Mem1(x) memset(x,-1,sizeof(x)) #define MemX(x) memset(x,0x3f,sizeof(x)) using namespace std; typedef long long ll; const int inf=0x3f3f3f; const double pi=acos(-1.0); const int MAXN=1e5+10; struct s{ int l,r; ll col,lazy; }tree[MAXN<<2]; int l,t,o;//长度,颜色数,询问次数 ll ans; void btree(int rt,int l,int r) { tree[rt].l=l; tree[rt].r=r; tree[rt].lazy=0; tree[rt].col=1; if (l==r){ return ; } int mid=(l+r)>>1; btree(rt<<1,l,mid); btree(rt<<1|1,mid+1,r); return ; } void pushdown(int rt) { if (tree[rt].lazy){ tree[rt<<1].col=tree[rt<<1|1].col=tree[rt].lazy; tree[rt<<1].lazy=tree[rt<<1|1].lazy=tree[rt].lazy; tree[rt].lazy=0; } return ; } void update(int rt,int a,int b,int c) { if (a>tree[rt].r||b<tree[rt].l){ return ; } else if (a<=tree[rt].l&&tree[rt].r<=b){ tree[rt].col=tree[rt].lazy=1<<(c-1); return ; } pushdown(rt); update(rt<<1,a,b,c); update(rt<<1|1,a,b,c); tree[rt].col=tree[rt<<1].col|tree[rt<<1|1].col; return ; } void query(int rt,int a,int b) { if (a>tree[rt].r||b<tree[rt].l){ return ; } else if (a<=tree[rt].l&&tree[rt].r<=b){ ans|=tree[rt].col; return ; } pushdown(rt); query(rt<<1,a,b); query(rt<<1|1,a,b); return ; } ll find(ll a) { int tmp=0; while (a){ if (a%2==1) tmp++; a>>=1; } return tmp; } int main() { scanf("%d%d%d",&l,&t,&o); btree(1,1,l); while (o--){ char str; int a,b,c; cin>>str; if (str=='C'){ scanf("%d%d%d",&a,&b,&c); update(1,a,b,c); } else{ scanf("%d%d",&a,&b); ans=0; if (a>b) query(1,b,a); else query(1,a,b); cout<<find(ans)<<endl; } } return 0; }