标签:des style http io color os ar for sp
对应POJ题目:点击打开链接
Time Limit: 1000MS | Memory Limit: 65536KB | 64bit IO Format: %I64d & %I64u |
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
Source
题意:1~N开始被刷上颜色1,有O个操作,C a,b,c 表示把a~b区间刷成颜色c; P a,b 表示求a~b区间共有多少种颜色。
思路:线段树;color[rt] 表示结点rt有哪几种颜色,用二进制表示;查询时不断并上符合要求的区间的值就可以了。这道题学习了求一个整数有多少个1的几种方法,还是有点收获的。。。
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<queue> #include<stack> #include<vector> #include<algorithm> #include<cstring> #include<string> #include<iostream> #define ms(x,y) memset(x,y,sizeof(x)) #define N 100000+10 const int MAXN=1000+10; const int INF=1<<30; using namespace std; int color[N<<2]; int ans; #if 0 int cal(int x)//求一个整数中1的个数普通方法,速度一般 { int cnt=0; while(x) { if(x&1) cnt++; x>>=1; } return cnt; } /* 一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减去1,那么原来处在整数最右边的1就会变成0,原来在1后面的所有 的0都会变成1。其余的所有位将不受到影响。举个例子:一个二进制数1100,从右边数起的第三位是处于最右边的一个1。减去1后,第三位变成0,它后面 的两位0变成1,而前面的1保持不变,因此得到结果是1011。 我们发现减1的结果是把从最右边一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位 开始所有位都会变成0。如1100&1011=1000。也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。那么 一个整数的二进制有多少个1,就可以进行多少次这样的操作。 */ int cal(int x)//速度较快 { int cnt=0; while(x) { ++cnt; x=(x-1)&x; } return cnt; } #endif //HAKMEM算法: int cal(unsigned x)//速度更快 { unsigned n; n = (x >> 1) & 033333333333; x = x - n; n = (n >> 1) & 033333333333; x = x - n; x = (x + (x >> 3)) & 030707070707; x = x%63; return x; } void updata(int rt, int left, int right, int l, int r, int c) { if(left==l && right==r){ color[rt]=1<<(c-1);//这里开始是直接=c,好久才发现问题。。。 return; } int cnt=cal(color[rt]);//如果该结点只有一种颜色,则向下更新 if(cnt==1){ color[rt<<1]=color[rt]; color[rt<<1|1]=color[rt]; } int mid=(left+right)>>1; if(mid>=r) updata(rt<<1, left, mid, l, r, c); else if(mid<l) updata(rt<<1|1, mid+1, right, l, r, c); else{ updata(rt<<1, left, mid, l, mid, c); updata(rt<<1|1, mid+1, right, mid+1, r, c); } color[rt]=color[rt<<1]|color[rt<<1|1];//合并 } void query(int rt, int left, int right, int l, int r) { if(l==left && right==r){ ans|=color[rt]; return; } if(left==right) return; int cnt=cal(color[rt]); if(cnt==1){ color[rt<<1]=color[rt]; color[rt<<1|1]=color[rt]; } int mid=(left+right)>>1; if(mid>=r) query(rt<<1, left, mid, l, r); else if(mid<l) query(rt<<1|1, mid+1, right, l, r); else{ query(rt<<1, left, mid, l, mid); query(rt<<1|1, mid+1, right, mid+1, r); } } int main() { //freopen("in.txt","r",stdin); int L,T,O; int a,b,c; char op; scanf("%d%d%d", &L,&T,&O); for(int i=1; i<(N<<2); i++) color[i]=1; while(O--) { scanf("%s", &op); if(op=='C'){ scanf("%d%d%d", &a,&b,&c); if(b<a){//不断WA,坑!网上看人的才知道a可能大于b。。。 int tmp=a; a=b; tmp=a; } updata(1,1,N,a,b,c); } else{ scanf("%d%d", &a,&b); if(b<a){ int tmp=a; a=b; tmp=a; } ans=0; query(1,1,N,a,b); printf("%d\n", cal(ans)); } } return 0; }
标签:des style http io color os ar for sp
原文地址:http://blog.csdn.net/u013351484/article/details/40681979