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
",i-1,ans[i]);
102         }
103         cout<<endl;
104     }
105 }
View Code
原文地址:https://www.cnblogs.com/thunder-110/p/10302782.html