poj 2777
首先数字最多只有 30 种,很容易想到状压,用一个 int 来表示一个区间数字出现的状态。
很容易想到用线段树来维护一个区间数字出现的状态。
#include"cstdio" #include"cctype" #include"algorithm" using namespace std; #define lc o*2 #define rc o*2+1 #define mid (l+r)/2 int read() { int c,x=0; while(!isdigit(c=getchar())); while(x=x*10+c-'0',isdigit(c=getchar())); return x; } int f[400001],c[400001]; void update(int o) { if(c[o]) f[o]=(1<<c[o]-1); else f[o]=f[lc]|f[rc]; } void push(int o) { if(c[o]) c[lc]=c[o],c[rc]=c[o],c[o]=0; update(lc); update(rc); } void change(int o,int l,int r,int L,int R,int v) { if(l>R || r<L) return; if(l>=L && r<=R) { c[o]=v; update(o); return; } push(o); change(lc,l,mid,L,R,v); change(rc,mid+1,r,L,R,v); update(o); } int query(int o,int l,int r,int L,int R) { if(l>R || r<L) return 0; if(l>=L && r<=R) return f[o]; push(o); return query(lc,l,mid,L,R)|query(rc,mid+1,r,L,R); } int calc(int k) { int res=0; for(;k;k>>=1) if(k&1) res++; return res; } int main() { c[1]=f[1]=1; int L=read(),T=read(),O=read(); while(O--) { char c; while(c=getchar(),c!='P' && c!='C'); if(c=='C') { int A=read(),B=read(),C=read(); if(A>B) swap(A,B); change(1,1,L,A,B,C); } else { int A=read(),B=read(); if(A>B) swap(A,B); printf("%d\n",calc(query(1,1,L,A,B))); } } return 0; }