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)也就是左闭右开的形式,这样就可以使得中间的那块区间不背忽略。

②题目都没给总区间长度,所以无论查询还是建树,我们都默认用1~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,1,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 }
时间: 2024-12-25 19:23:30

ZOJ 1610 Count the Colors(区间染色)的相关文章

ZOJ 1610 Count the Colors (线段树区间更新)

题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头输出. //ZOJ 1610 #include <cstdio> #include <cstring> #include <iostream> using namespace std ; int p[8010*4],lz[8010*4] ,hashh[8010*4],has

zoj 1610 Count the Colors

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=610 先用线段树维护区间颜色的覆盖,然后在把区间的颜色映射到数组,再从数组统计颜色. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 100000 5 using namespace std; 6 7 int n; 8 int min1; 9

ZOJ 1610 Count the Colors【题意+线段树区间更新&amp;&amp;单点查询】

任意门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610 Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent

zoj 1610 Count the Colors 【区间覆盖 求染色段】

Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones. Your task is counting the segments of different colors you can s

ZOJ 1610——Count the Colors——————【线段树区间替换、求不同颜色区间段数】

Count the Colors Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit Status Practice ZOJ 1610 Description Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent o

ZOJ 1610 Count the Colors(线段树,区间覆盖,单点查询)

Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones. Your task is counting the segments of different colors you can s

ZOJ 1610 Count the Colors(线段树lazy+暴力统计)

Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones. Your task is counting the segments of different colors you can s

ZOJ 1610 Count the Colors (线段树成段更新)

题意 : 给出 n 个染色操作,问你到最后区间上能看见的各个颜色所拥有的区间块有多少个 分析 : 使用线段树成段更新然后再暴力查询总区间的颜色信息即可,这里需要注意的是给区间染色,而不是给点染色,所以对于区间(L, R)我们只要让左端点+1即可按照正常的线段树操作来做. #include<bits/stdc++.h> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; co

ZOJ - 1610 Count the Colors 线段树区间修改

Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones. Your task is counting the segments of different colors you can see at last. InputThe first line of each data set contains exactly o