ZOJ 1610 Count the Colors(区间染色)

题目大意:多组数据,每组给一个n(1=<n<=8000),下面有n行,每行有l,r,color(1=<color<=8000),表示将l~r颜色变为color,最后求各种颜色(1~8000)所占区段数,如果所占区段为0则不用输出。

解题思路:基本还是跟区间染色问题差不多,但要注意一些东西

①这里l,r指的是端点。比如

3

1 4 1

1 2 2

3 4 3

这组数据最后输出结果为:

1 1

2 1

3 1

原因是还有[2,3]这一段颜色为1,处理办法是将更新函数写成(1,l+1,r,color)也就是左闭右开的形式,这样就可以使得中间的那块区间不背忽略。

②题目都没给总区间长度,所以无论查询还是建树,我们都默认用0~8000。

③关于查询各颜色所占区段数的问题,不可能直接通过线段树找到个颜色区段数,因为还要考虑两个子树是相邻的情况。所以可以通过使用一个vis[i]数组,记录各区间的颜色,最后只要简单处理一下就可以得到结果了。

 1 #include<cstring>
 2 #include<stdio.h>
 3 #include<iostream>
 4 #define LC(a) ((a<<1))
 5 #define RC(a) ((a<<1)+1)
 6 #define MID(a,b) ((a+b)>>1) 
 7 using namespace std;
 8 typedef long long ll;
 9 const int N=8e3*4;
10 
11 struct node{
12     ll l,r;
13     ll color;//颜色为-2表示混合色 
14 }tree[N];
15 
16 ll ans[N];
17 ll vis[N]; 
18 //下推 
19 void pushdown(ll p){
20     tree[RC(p)].color=tree[LC(p)].color=tree[p].color;
21 }
22 //上推 
23 void pushup(ll p){
24     tree[p].color=(tree[LC(p)].color==tree[RC(p)].color?tree[LC(p)].color:-2);
25 }
26 
27 void build(ll p,ll l,ll r){
28     tree[p].l=l;
29     tree[p].r=r;
30     tree[p].color=-1;//初始化颜色因题意而定 
31     if(l==r){
32         return;
33     }
34     build(LC(p),l,MID(l,r));
35     build(RC(p),MID(l,r)+1,r);
36 }
37 
38 void update(ll p,ll l,ll r,ll color){
39     if(r<tree[p].l||l>tree[p].r)
40         return;
41     if(tree[p].color==color)
42         return;
43     if(l<=tree[p].l&&r>=tree[p].r){
44         tree[p].color=color;        
45         return;
46     }
47     //**释放lazy标记 
48     if(tree[p].color!=-2){
49         pushdown(p);
50     }
51     update(LC(p),l,r,color);
52     update(RC(p),l,r,color);
53     pushup(p);
54 }
55 
56 void query(ll p,ll l,ll r){
57     if(r<tree[p].l||l>tree[p].r)
58         return;
59     
60     //纯色,不用再找下去 
61     if(tree[p].color!=-2){
62         //**使用vis数组记录区间颜色 
63         for(int i=tree[p].l;i<=tree[p].r;i++){
64             vis[i]=tree[p].color;
65         }
66         return;
67     }        
68     query(LC(p),l,r);
69     query(RC(p),l,r);
70 }
71 
72 int main(){
73     ios::sync_with_stdio(false);
74     ll n;
75     //注意是从0~n 
76     while(cin>>n){
77         build(1,0,8000);
78         ll maxc=0;
79         for(int i=1;i<=n;i++){
80             ll l,r,color;
81             cin>>l>>r>>color;
82             maxc=max(maxc,color);
83             update(1,l+1,r,color);
84         }
85         memset(ans,0,sizeof(ans));
86         memset(vis,-1,sizeof(vis));
87         query(1,1,8000);
88         //处理vis数组,统计各区段数 
89         for(int i=1;i<=8000;i++){
90             if(vis[i]!=vis[i-1]&&vis[i]!=-1)
91                 ans[vis[i]]++;
92         }
93         for(int i=0;i<=maxc;i++){
94             if(ans[i])
95                 cout<<i<<" "<<ans[i]<<endl;
96         }
97         cout<<endl;
98     }
99 }
原文地址:https://www.cnblogs.com/fu3638/p/7138774.html