题意: 有一个长度为 N 的墙,定义两种操作:
1 a b c 将 区间[a,b]涂成 c颜色
2 a b c 询问区间[a,b]中c颜色的的个数。
分析 : 区间合并类线段树。
#include#include #define clr(x)memset(x,0,sizeof(x))#define maxn 100005#define max(a,b)(a)>(b)?(a):(b)#define min(a,b)(a)<(b)?(a):(b)int hi[maxn<<2];int lo[maxn<<2];int col[maxn<<2];int add[maxn<<2];void creat(int l,int r,int rt){ if(l==r) { scanf("%d",&col[rt]); add[rt]=-1; hi[rt]=lo[rt]=col[rt]; return; } int mid=(l+r)>>1; creat(l,mid,rt<<1); creat(mid+1,r,rt<<1|1); if(add[rt<<1]==-1&&add[rt<<1|1]==-1&&col[rt<<1]==col[rt<<1|1]) { add[rt]=-1; col[rt]=col[rt<<1]; } else { add[rt]=0; col[rt]=-1; } hi[rt]=max(hi[rt<<1],hi[rt<<1|1]); lo[rt]=min(lo[rt<<1],lo[rt<<1|1]);}void update(int c,int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) { add[rt]=-1; col[rt]=c; hi[rt]=lo[rt]=c; return; } if(add[rt]==-1) { add[rt<<1]=add[rt<<1|1]=add[rt]; col[rt<<1]=col[rt<<1|1]=col[rt]; hi[rt<<1]=hi[rt<<1|1]=col[rt]; lo[rt<<1]=lo[rt<<1|1]=col[rt]; add[rt]=0; } int mid=(l+r)>>1; if(L<=mid) update(c,L,R,l,mid,rt<<1); if(R>mid) update(c,L,R,mid+1,r,rt<<1|1); if(add[rt<<1]==-1&&add[rt<<1|1]==-1&&col[rt<<1]==col[rt<<1|1]) { add[rt]=-1; col[rt]=col[rt<<1]; } else { add[rt]=0; col[rt]=-1; } hi[rt]=max(hi[rt<<1],hi[rt<<1|1]); lo[rt]=min(lo[rt<<1],lo[rt<<1|1]);}int query(int c,int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) { if(add[rt]==-1&&col[rt]==c) return (r-l+1); else if(c hi[rt]) return 0; } if(add[rt]==-1) { add[rt<<1]=add[rt<<1|1]=add[rt]; col[rt<<1]=col[rt<<1|1]=col[rt]; hi[rt<<1]=hi[rt<<1|1]=col[rt]; lo[rt<<1]=lo[rt<<1|1]=col[rt]; add[rt]=0; } int mid=(l+r)>>1; int tot=0; if(L<=mid) tot+=query(c,L,R,l,mid,rt<<1); if(R>mid) tot+=query(c,L,R,mid+1,r,rt<<1|1); return tot;}int main(){ int n,m,op,a,b,c,res; while(scanf("%d%d",&n,&m)!=EOF) { creat(1,n,1); while(m--) { scanf("%d%d%d%d",&op,&a,&b,&c); if(op==1) update(c,a+1,b+1,1,n,1); else { res=query(c,a+1,b+1,1,n,1); printf("%d\n",res); } } } return 0;}