标签:each simple make 情况 == 种类 order gre 查询
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 53639 | Accepted: 16153 |
Description
Input
Output
Sample Input
2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2
Sample Output
2
1
题目链接:
http://poj.org/problem?id=2777
题目大意:
给L长度的木板涂色,一开始木板颜色相同,有T种颜色可用,O(不是零是 ou )次操作。每次操作有两种情况,一种是改变木板的颜色也就是给木板的某个区间涂色,另一种是询问给定区间的颜色种类数量。
题目分析:
这题比较明显是使用线段树解决问题,但是有一个问题是:超时。那么如何解决这个问题呢,这时候就引进了一个很优秀的操作————懒标记。
懒标记是什么呢?“懒”的意思很明显了,就是说在不涉及某个节点的情况下,选择性的变懒,不去改变。举个例子:
如果改变区间的颜色,那么我们可以不去找到区间内每个叶子然后改变每个叶子的颜色,而是找到在这个区间内的另外的区间(可能是一个区间,也可能是很多个区间,也有可能包括了一个区间和n个叶子,也有可能只有叶子),把找到的区间改变颜色,并把区间懒标记。
懒标记后,如果再次查询到该节点,那么需要做下推操作,即把该节点的颜色,下推给子节点,改变子节点的颜色,并把该节点懒标记清空。
对于颜色的存储,这题还是需要注意的。我们很容易想到存储每个节点区间的颜色种类数,但是这样存储问题就来了,怎么确定子节点中颜色是否相同。所以有引进一个骚操作,二进制表示法。
我们可以看到颜色的种类不超过30种,所以可以用一位二进制表示一种颜色,即颜色一为(1),颜色二为(10),颜色三为(100),颜色四为(1000),依次类推。
那么我们存储父节点颜色怎么存储呢? 或操作(|)。
tree[k].color=tree[k<<1].color|tree[k<<1|1].color;
解释一下:或操作,如果颜色相同,那么结果仍保存该颜色;如果子节点一个有该颜色,另一个没有该颜色,操作结果仍然有该颜色;如果两个子节点都没有该颜色,那么结果也没有该颜色。
最后得到的结果只需要判断在二进制下有几个1就可以了。
还要注意一个坑就是 A和B谁大谁小不确定。
AC代码如下:
#include<stdio.h> const int MAX=1e6+5; struct a{ int left,right; int lazy,ans; }tree[MAX<<2]; void init(int length) //懒标记初始化 { for(int i=1;i<=length;i++) { tree[i].lazy=0; } } void btree(int k,int l,int r) //建树操作 { tree[k].left=l;tree[k].right=r; if(l==r) { tree[k].ans=1;return ; } int mid=(l+r)>>1; btree(k<<1,l,mid); btree(k<<1|1,mid+1,r); tree[k].ans=(tree[k<<1].ans|tree[k<<1|1].ans); } void push_down(int k) //下推 { if(tree[k].left==tree[k].right) return ; tree[k<<1].lazy=tree[k].lazy; tree[k<<1|1].lazy=tree[k].lazy; tree[k<<1].ans=1<<(tree[k].lazy-1); tree[k<<1|1].ans=1<<(tree[k].lazy-1); tree[k].lazy=0; } void datetree(int k,int l,int r,int co) //涂色 { if(tree[k].left>=l&&tree[k].right<=r) { tree[k].ans=1<<(co-1); tree[k].lazy=co; return ; } if(tree[k].lazy) push_down(k); int mid=(tree[k].left+tree[k].right)>>1; if(mid<l) { datetree(k<<1|1,l,r,co); } else if(mid>=r) { datetree(k<<1,l,r,co); } else { datetree(k<<1,l,r,co); datetree(k<<1|1,l,r,co); } tree[k].ans=(tree[k<<1].ans|tree[k<<1|1].ans); } int ans; void query(int k,int l,int r) //询问 { if(tree[k].left>=l&&tree[k].right<=r) { ans=(ans|tree[k].ans); return ; } if(tree[k].lazy) push_down(k); int mid=(tree[k].left+tree[k].right)>>1; if(mid<l) { query(k<<1|1,l,r); } else if(mid>=r) { query(k<<1,l,r); } else { query(k<<1,l,r); query(k<<1|1,l,r); } } int main() { int L,color,q; char n[10]; scanf("%d%d%d",&L,&color,&q); init(L); btree(1,1,L); while(q--) { scanf("%s",n); if(n[0]==‘C‘) { int a,b,c; scanf("%d%d%d",&a,&b,&c); if(a>b){ int t=a;a=b;b=t; } datetree(1,a,b,c); } else { int a,b; ans=0; int cnt=0; scanf("%d%d",&a,&b); if(a>b){ int t=a;a=b;b=t; } query(1,a,b); while(ans) { if(ans%2) cnt++; ans/=2; } printf("%d\n",cnt); } } return 0; }
POJ - 2777——Count Color(懒标记线段树二进制)
标签:each simple make 情况 == 种类 order gre 查询
原文地址:https://www.cnblogs.com/noback-go/p/10541560.html