Count the Colors 线段树
题意:
n范围[1,8000] , li 和 ri 的范围[0,8000]。 n个操作,每个操作是把 [li , ri]内的点修改成一个颜色c。 n个操作过后,按颜色从小到大 输出每种颜色分别有几块。
1 #include<iostream> 2 #include<cstdio> 3 #include <cctype> 4 #include<algorithm> 5 #include<cstring> 6 #include<cmath> 7 #include<string> 8 #include<cmath> 9 #include<set> 10 #include<vector> 11 #include<stack> 12 #include<queue> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define mem(a,x) memset(a,x,sizeof(a)) 17 #define se second 18 #define fi first 19 const ll mod=1e9+7; 20 const int INF= 0x3f3f3f3f; 21 const int N=1e5+5; 22 23 int add[N<<2]; 24 int flag; //flag判断相邻两个区间的颜色是否相同 25 int ans[N<<2]; 26 27 void push_down(int rt) 28 { 29 if(add[rt]>0) 30 { 31 add[rt<<1]= add[rt]; 32 add[rt<<1|1]= add[rt]; 33 add[rt]=-1; 34 } 35 } 36 void Built(int l,int r,int rt) 37 { 38 add[rt]=0; 39 if(l==r) return; 40 int m=l+r>>1; 41 Built(l,m,rt<<1); 42 Built(m+1,r,rt<<1|1); 43 } 44 45 void update(int x,int y,int c,int l,int r,int rt) 46 { 47 if(x<=l && r<=y) 48 { 49 add[rt]=c; 50 return; 51 } 52 push_down(rt); 53 int m=l+r>>1; 54 if(x<=m) update(x,y,c,l,m,rt<<1); //当寻找一个区间的时候,路径上的值全改成c 55 if(m<y) update(x,y,c,m+1,r,rt<<1|1);//当寻找一个区间的时候,路径上的值全改成c 56 add[rt]=-1; //寻找到了之后,把回头的路径全部改成-1,说明如果顺着这些点下来,一定能找到区间 57 } 58 59 void query(int l,int r,int rt) 60 { 61 if(flag==add[rt]) return; 62 if(add[rt]==0) //一次也没有被涂过 63 { 64 flag=0; return; 65 } 66 if(add[rt]>0) 67 { 68 if(flag!=add[rt]) //不是同一块海报 69 { 70 flag=add[rt]; 71 ans[add[rt]]++; 72 } 73 return; 74 } 75 76 //接下来是如果add[rt]== -1 ,表示顺着这个点 一定能找到区间 77 if(l==r) 78 return; 79 int m=l+r>>1; 80 query(l,m,rt<<1); 81 query(m+1,r,rt<<1|1); 82 } 83 int main() 84 { 85 int x,y,z,n,m; 86 while(scanf("%d",&n)==1) 87 { 88 mem(add,0); //0表示该点没有涂色。 89 mem(ans,0); 90 Built(0,8000,1); 91 92 for(int i=1;i<=n;i++) 93 { 94 scanf("%d%d%d",&x,&y,&z); 95 update(x, y-1, z+1, 0,8000,1); 96 } 97 query(0,8000,1); 98 99 for(int i=0;i<=8000;i++) 100 { 101 if(ans[i]) printf("%d %d\n",i-1,ans[i]); 102 } 103 cout<<endl; 104 } 105 }