Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 40234 | Accepted: 12141 |
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
首先这道题是区间颜色覆盖问题,很容易想到线段树。然后我们又发现颜色数≤30,所以这道题就可以和位运算集合到一起,这个思路很巧妙。
注意:A可能大于B,这时需要交换两个数。(我一开始没发现结果RE了......T T)
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define LL long long #define MAXN 100005 #define pa pair<int,int> using namespace std; int l,c,n,x,y,z; char ch; struct tree_type { int l,r,w,tag; }t[MAXN*4]; int read() { int ret=0,flag=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();} while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();} return ret*flag; } void pushup(int k) { t[k].w=t[k<<1].w|t[k<<1|1].w; } void update(int k,int z) { t[k].tag=t[k].w=z; } void pushdown(int k) { if (t[k].tag==0) return; update(k<<1,t[k].tag); update(k<<1|1,t[k].tag); t[k].tag=0; } void build(int k,int x,int y) { t[k].l=x; t[k].r=y; t[k].tag=0; if (x==y) {t[k].w=1;return;} int mid=(x+y)>>1; build(k<<1,x,mid); build(k<<1|1,mid+1,y); pushup(k); } void cover(int k,int x,int y,int z) { if (t[k].l==x&&t[k].r==y) {update(k,z);return;} pushdown(k); int mid=(t[k].l+t[k].r)>>1; if (mid>=y) cover(k<<1,x,y,z); else if (mid+1<=x) cover(k<<1|1,x,y,z); else cover(k<<1,x,mid,z),cover(k<<1|1,mid+1,y,z); pushup(k); } int query(int k,int x,int y) { if (t[k].l==x&&t[k].r==y) return t[k].w; pushdown(k); int mid=(t[k].l+t[k].r)>>1; if (mid>=y) return query(k<<1,x,y); else if (mid+1<=x) return query(k<<1|1,x,y); else return (query(k<<1,x,mid)|query(k<<1|1,mid+1,y)); } int calc(int x) { int ans=0; for(;x;x>>=1) ans+=x&1; return ans; } int main() { l=read();c=read();n=read(); build(1,1,l); F(i,1,n) { ch=getchar();while (ch!='C'&&ch!='P') ch=getchar(); x=read();y=read(); if (x>y) swap(y,x); if (ch=='C') z=read(),cover(1,x,y,1<<(z-1)); else printf("%d\n",calc(query(1,x,y))); } return 0; }