题意:
??????? 一段区间从1-n的初始颜色为1,每次进行两种操作1,C a b c 把[a,b]这个区间染成颜色c。2,P a b查询[a,b]区间内有多少种颜色。
?
思路:
????? 这一题的关键在于用二进制存储一个区间内的颜色数量,新增颜色时对当前区间进行或操作来实现。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int nMax = 100000; struct { int l , r , clo , num; }node[nMax*3]; void build(int l ,int r ,int u){ node[u].l = l; node[u].r = r; node[u].clo = 1; node[u].num = 1; if(l == r){ return; } int m = (l + r)>> 1; build(l , m , u*2); build(m + 1, r , u*2+1); } void update(int left ,int right ,int p ,int u){ // cout<<left <<" tt "<<right<<" "<<u<<endl; if ( p == node[u].clo )return; if(left == node[u].l && right == node[u].r){ node[u].clo = p; node[u].num = 1<<(p-1); return; } if(node[u].clo != 0){ node[2*u].clo = node[u].clo; node[2*u].num = node[u].num; node[2*u+1].clo = node[u].clo; node[2*u+1].num = node[u].num; node[u].clo = 0; node[u].num = 0; } int m = (node[u].l + node[u].r)>>1; if(left <= m){ update(left , min(right , m), p ,u*2); } if(right >= m+1){ update(max(left , m + 1) ,right ,p ,u*2+1); } node[u].num |= (node[2*u].num); node[u].num |= (node[2*u+1].num); } int ans; void query(int left ,int right ,int u){ if(node[u].clo != 0){ // cout<<u<<" dddd "<<node[u].num<<" "<<node[u].clo<<endl; ans |= node[u].num; return; } int m = (node[u].l + node[u].r)>>1; if(right <= m){ query(left , right , u*2); return; } if(left >= m+1){ query(left ,right , u*2 +1); return ; } query(left , m , u*2); query(m+1 , right , u*2 + 1); } int gao(int a){ int res = 0; while(a){ if(a & 1)res++; a >>= 1; } return res; } int main(){ int n ,k ,m ,i ,j , a, b ,c; char str[5]; while( scanf("%d%d%d",&n,&k,&m)!=EOF){ build(1 ,n ,1); while(m--){ scanf("%s",str); if( str[0] == ‘C‘){ scanf("%d%d%d",&a,&b,&c); update(a ,b ,c ,1); }else{ scanf("%d%d",&a,&b); ans = 0; query(a ,b ,1); // cout<<ans<<endl; printf("%d\n",gao(ans)); } } } return 0; }
??
?
原文:http://bbezxcy.iteye.com/blog/2161642