标签: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