poj-2528 Mayor's posters

离散化 + 线段树

坐标按从小到大排序,再构造映射。。

poj-2528 Mayor's posters View Code
1 // color=0表示未着色或为杂色
2  
3 #include < cstdio >
4 #include < cstring >
5 #include < algorithm >
6   using namespace std;
7
8 const int MAXN = 40000 + 5 ;
9 const int MAX_R = 10000000 + 5 ;
10
11 int n, ans;
12 bool vis[MAXN] = {};
13 struct SData{ // 记录数据
14 int b, e;
15 };
16 SData data[MAXN];
17
18 struct node{ // 线段树节点
19 int l, r;
20 int color;
21 };
22 node tree[MAXN * 3 ];
23
24 struct line{ // s表示端点、num表示该端点是哪个poster的
25 int s, num;
26 };
27 line L[MAXN * 3 ];
28
29 // 建树
30 void build( int i, int ll, int rr){
31 tree[i].l = ll; tree[i].r = rr;
32 tree[i].color = 0 ; // 未着色
33 if (rr != ll){
34 int mid = (ll + rr) / 2 ;
35 build( 2 * i, ll, mid);
36 build( 2 * i + 1 , mid + 1 , rr);
37 }
38 }
39
40 //
41 void insert( int i, int ll, int rr, int cc){
42 if (tree[i].l == ll && tree[i].r == rr){
43 tree[i].color = cc;
44 return ;
45 }
46 if (tree[i].r == tree[i].l)
47 return ;
48
49 if (tree[i].color > 0 && tree[i].color != cc){
50 tree[i << 1 ].color = tree[i].color;
51 tree[(i << 1 ) + 1 ].color = tree[i].color;
52 tree[i].color = 0 ;
53 }
54 int mid = (tree[i].l + tree[i].r) >> 1 ;
55 if (rr <= mid)
56 insert(i << 1 , ll, rr, cc);
57 else if (ll > mid)
58 insert((i << 1 ) + 1 , ll, rr, cc);
59 else {
60 insert(i << 1 , ll, mid, cc);
61 insert((i << 1 ) + 1 , mid + 1 , rr, cc);
62 }
63 }
64
65 void sum ( int i )
66 {
67 if ( tree[i].color )
68 {
69 if ( ! vis[tree[i].color] )
70 {
71 vis[tree[i].color] = true ;
72 ans ++ ;
73 }
74 return ;
75 }
76 sum( i << 1 );
77 sum( (i << 1 ) + 1 );
78 }
79
80 bool cmp(line a, line b){
81 return a.s < b.s;
82 }
83
84 int main(){
85 int c;
86 scanf( " %d " , & c);
87 while (c -- ){
88 scanf( " %d " , & n);
89
90 for ( int i = 0 ; i < n; i ++ ){
91 scanf( " %d%d " , & data[i].b, & data[i].e);
92
93 L[ 2 * i].s = data[i].b; L[ 2 * i].num =- (i + 1 ); // 负数表示是poster的左端点
94 L[ 2 * i + 1 ].s = data[i].e; L[ 2 * i + 1 ].num = i + 1 ; // 正数表示是右端点
95 }
96   
97
98 // 离散化……
99 sort(L, L + 2 * n, cmp);
100 int cnt = 1 , temp = L[ 0 ].s;
101 for ( int i = 0 ; i < 2 * n; i ++ ){
102 if (L[i].s != temp){
103 cnt ++ ;
104 temp = L[i].s;
105 }
106 if (L[i].num < 0 ) // 如果是左端点
107 data[ - L[i].num - 1 ].b = cnt;
108 else // 如果是右端点
109 data[L[i].num - 1 ].e = cnt;
110 }
111
112
113 // 线段树……
114 build( 1 , 1 , cnt);
115
116 for ( int i = 0 ; i < n; i ++ ){
117 insert( 1 , data[i].b, data[i].e, i + 1 );
118 }
119
120
121 memset(vis, 0 , sizeof (vis));
122 ans = 0 ;
123 sum( 1 );
124
125 printf( " %d\n " , ans);
126
127 }
128
129
130 return 0 ;
131 }

另附:

【转】

关于这个题离散化的问题,在discuss里有人说测试数据是错的,如果按照一般的离散化的方法去写有种数据不能过

1 10

1 5

8 10

如果像我下面的代码那样写离散化的结果

1 4

1 2

3 4

很明显6-7这条线段在离散化时被消除了

如果想得到正确的结果其实只用在离散化时修改一下就可以了。

如果这两条线段的两个端点是相邻的,cnt++

不相邻cnt+=2;

正确的离散化代码:

poj-2528 Mayor's posters View Code
1 for (i = 1 ;i < 2 * n;i ++ )
2 {
3 if (L[i].s != L[i - 1 ].s)
4 {
5 if (L[i - 1 ].s + 1 == L[i].s)
6 cnt += 1 ;
7 else
8 cnt += 2 ;
9 }
10 if (L[i].flag)
11 p[L[i].num].x = cnt;
12 else
13 p[L[i].num].y = cnt;
14 }

你可能感兴趣的:(post)