标签:线段树
题意是给你n个连续的点(1-n) m次操作 开始每个点都为2
两种操作
1:把一段区间的点变为c
2:询问区间有多少种点
很明显的线段树 对每个节点
flash表示该节点是否全为一样的数 若是 则flash=这个数否则 flash=-1;
数组color记录该节点输得状态 1表示有0表示没有(我开成字符型 之前为int超类存了 真是无语)
然后 有更新和查询操作
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; #define LL(x) (x<<1) #define RR(x) ((x<<1)|1) struct node { char color[31]; int flash; }num[3* 1000000]; int leap[31]; int change(int mark,int k) { for(int i=1;i<=30;i++) { num[mark].color[i]=‘0‘; } num[mark].color[k]=‘1‘; return 0; } int deal(int L,int R,int mark) { num[mark].flash=2; change(mark,2); int mid=(L+R)/2; if(L==R) return 0; deal(L,mid,LL(mark)); deal(mid+1,R,RR(mark)); return 0; }//注意题目说开始时每个点都是2 int update(int L,int R,int left,int right,int mark,int k) { int mid=(L+R)/2; if(num[mark].flash==k) return 0;//一个小优化 if(L==left&&R==right) { num[mark].flash=k; change(mark,k); return 0; } if(num[mark].flash>0) { num[LL(mark)].flash=num[RR(mark)].flash=num[mark].flash; change(LL(mark),num[mark].flash); change(RR(mark),num[mark].flash); } if(right<=mid) { update(L,mid,left,right,LL(mark),k); } else if(left>mid) { update(mid+1,R,left,right,RR(mark),k); } else { update(L,mid,left,mid,LL(mark),k); update(mid+1,R,mid+1,right,RR(mark),k); } for(int i=1;i<=30;i++) { if(num[LL(mark)].color[i]==‘1‘||num[RR(mark)].color[i]==‘1‘) { num[mark].color[i]=‘1‘; } else num[mark].color[i]=‘0‘; } if(num[LL(mark)].flash==num[RR(mark)].flash&&num[LL(mark)].flash>0) num[mark].flash=num[LL(mark)].flash; else num[mark].flash=-1; return 0; } int find(int L,int R,int left,int right,int mark) { int mid=(L+R)/2; if(num[mark].flash!=-1) { leap[num[mark].flash]=1; return 0; } if(L==left&&R==right) { for(int i=1;i<=30;i++) { if(num[mark].color[i]==‘1‘) leap[i]=1; } } if(right<=mid) { find(L,mid,left,right,LL(mark)); } else if(left>mid) { find(mid+1,R,left,right,RR(mark)); } else { find(L,mid,left,mid,LL(mark)); find(mid+1,R,mid+1,right,RR(mark)); } return 0; } int main() { int n,m,i,j,a,b,c; char str[5]; while(~scanf("%d%d",&n,&m),n+m) { deal(1,n,1); for(j=1;j<=m;j++) { scanf("%s",str); if(str[0]==‘P‘) { scanf("%d%d%d",&a,&b,&c); update(1,n,a,b,1,c); } else { scanf("%d%d",&a,&b); memset(leap,0,sizeof(leap)); find(1,n,a,b,1); int d=1; for(i=1;i<=30;i++) { if(leap[i]) { if(d!=1) printf(" "); printf("%d",i); d++; } } printf("\n"); } } } return 0; }
标签:线段树
原文地址:http://blog.csdn.net/zxf654073270/article/details/41651627