线段树专辑——pku 2528 Mayor's posters

http://poj.org/problem?id=2528

又是一道区间染色问题,经典问题,自然有经典解法:为线段树添加一个cover域,当cover的值为-1的时候,则说明该区间是有多种颜色组成的。当cover为一个非-1的值时,说明该区间为cover一种颜色组成。更新的时候只需要将单色的区间信息向下传递即可

这题唯一要做的,或许就是离散化吧。离散化就是利用数组的下标与其值一一对应的映射关系的一种hash。

View Code
  1 #include<iostream>
2 #include<string>
3 #include<algorithm>
4 using namespace std;
5
6 struct node
7 {
8 int l;
9 int r;
10 int cover;
11 };
12
13 node tree[100000];
14 long xx[20001];
15 int len,n;
16
17 struct post
18 {
19 long l;
20 long r;
21 };
22
23 post num[10001];
24
25 int find(long x) //二分查找某一个X在数组中对应的下标
26 {
27 int l=0,r=len,mid;
28 while(l<=r)
29 {
30 mid=(l+r)>>1;
31 if(xx[mid]==x)
32 return mid;
33 if(xx[mid]<x)
34 l=mid+1;
35 else
36 r=mid-1;
37 }
38 return l;
39 }
40
41 void build(int i,int l,int r)
42 {
43 tree[i].l=l;
44 tree[i].r=r;
45 tree[i].cover=0;
46 if(l==r)
47 return;
48 int mid=(l+r)>>1;
49 build(i<<1,l,mid);
50 build(i<<1|1,mid+1,r);
51 }
52
53 void updata(int i,int l,int r,int w)
54 {
55 if(tree[i].l>r || tree[i].r<l)
56 return;
57 if(tree[i].l>=l && tree[i].r<=r)
58 {
59 tree[i].cover=w;
60 return;
61 }
62 if(tree[i].cover!=-1) //线段是单色的,那么向下传递
63 {
64 tree[i<<1].cover=tree[i<<1|1].cover=tree[i].cover;
65 tree[i].cover=-1; //传递过后,将其标记为混色
66 }
67 updata(i<<1,l,r,w);
68 updata(i<<1|1,l,r,w);
69 }
70
71 int ans;
72 int v[10001]; //用于标记重复的颜色统计
73
74 void query(int i)
75 {
76 if(tree[i].cover!=-1) //单色线段,记录它的颜色
77 {
78 if(!v[tree[i].cover])
79 {
80 v[tree[i].cover]=1;
81 ans++;
82 }
83 return;
84 }
85 if(tree[i].l==tree[i].r)
86 return;
87 query(i<<1);
88 query(i<<1|1);
89 }
90
91 int main()
92 {
93 int cas,i,j;
94 freopen("in.txt","r",stdin);
95 scanf("%d",&cas);
96 while(cas--)
97 {
98 scanf("%d",&n);
99 j=0;
100 for(i=0;i<n;i++)
101 {
102 scanf("%ld%ld",&num[i].l,&num[i].r);
103 xx[j++]=num[i].l;
104 xx[j++]=num[i].r;
105 }
106 sort(xx,xx+j);
107 len=1;
108 for(i=1;i<j;i++) //取消重复的数
109 {
110 if(xx[i-1]!=xx[i])
111 {
112 xx[len++]=xx[i];
113 }
114 }
115 len--;
116 build(1,0,len);
117 for(i=0;i<n;i++)
118 {
119 int a=find(num[i].l); //离散化后查找
120 int b=find(num[i].r);
121 updata(1,a,b,i+1);
122 }
123 ans=0;
124 memset(v,0,sizeof(v));
125 query(1);
126 printf("%d\n",ans);
127 }
128 return 0;
129 }



原文地址:https://www.cnblogs.com/ka200812/p/2244501.html