经典的线段树的题,线段染色问题。跟“Mayor's Posters”那题差不多,只不过这题有多次查询。
需要注意的是给的区间[a,b],a可能会大于b。
#include <stdio.h> #include <string.h> #define N 100001 int n,m,k,ans; int vis[31]; int color[4*N]; void pushdown(int cur,int x,int y) { int ls=cur<<1,rs=cur<<1|1; if(color[cur]) { color[ls]=color[rs]=color[cur]; color[cur]=0; } } void build(int cur,int x,int y) { int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1; color[cur]=0; if(x==y) return; build(ls,x,mid); build(rs,mid+1,y); } void change(int cur,int x,int y,int s,int t,int c) { int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1; if(x>=s && y<=t) { color[cur]=c; return; } pushdown(cur,x,y); if(mid>=s) change(ls,x,mid,s,t,c); if(mid+1<=t) change(rs,mid+1,y,s,t,c); } int get(int cur,int x,int y) { int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1; if(color[cur]) { if(vis[color[cur]]==0) { vis[color[cur]]=1; return 1; } return 0; } return get(ls,x,mid)+get(rs,mid+1,y); } void query(int cur,int x,int y,int s,int t) { int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1; if(color[cur]) //少了此处会TLE { if(vis[color[cur]]==0) ans++; vis[color[cur]]=1; return; } if(x>=s && y<=t) { ans+=get(cur,x,y); return; } pushdown(cur,x,y); if(mid>=s) query(ls,x,mid,s,t); if(mid+1<=t) query(rs,mid+1,y,s,t); } int main() { freopen("in.txt","r",stdin); int x,y,z; char c; while(~scanf("%d%d%d",&n,&k,&m)) { build(1,1,n); color[1]=1; while(m--) { c=0; while(c!='C' && c!='P') scanf("%c",&c); scanf("%d%d",&x,&y); if(x>y) { int tmp=x; x=y,y=tmp; } if(c=='P') { memset(vis,0,sizeof(vis)); ans=0; query(1,1,n,x,y); printf("%d\n",ans); } else { scanf("%d",&z); change(1,1,n,x,y,z); } } } return 0; }