# BZOJ 4631: 踩气球

## 4631: 踩气球

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 267  Solved: 138
[Submit][Status][Discuss]

## Description

SHUXK 要进行Q次操作，每次从某一个盒子里拿出一个没被踩爆的气球，然后熊孩子们就会立刻把它踩爆。

## Input

N < = 10^5 ,M < = 10^5 �,Q < = 10^5

5 3
1 1 1 1 1
5 5
2 2
1 3
5
4
2
5
2
3

0
1
1
2
3
【样例说明】

## Source

[Submit][Status][Discuss]

  1 #include<bits/stdc++.h>
2
3 #define mxn 100005
4 #define mxm 8000005
5
6 #define min(a, b) (a < b ? a : b)
7 #define max(a, b) (a > b ? a : b)
8
9 int n, m;
10
11 int a[mxn];
12
13 struct pair {
14     int x, y;
15 }pt[mxn];
16
17 inline bool cmp(const pair &a, const pair &b) {
18     if (a.x != b.x)
19         return a.x < b.x;
20     else
21         return a.y < b.y;
22 }
23
24 int tt;
25 int sm[mxm];
26 int ls[mxm];
27 int rs[mxm];
28
29 int root[mxn];
30
31 void insert(int &a, int b, int l, int r, int p) {
32     a = ++tt;
33
34     ls[a] = ls[b];
35     rs[a] = rs[b];
36     sm[a] = sm[b] + 1;
37
38     if (l == r)return;
39
40     int d = (l + r) >> 1;
41
42     if (p <= d)
43         insert(ls[a], ls[b], l, d, p);
44     else
45         insert(rs[a], rs[b], d + 1, r, p);
46 }
47
48 int query(int a, int b, int l, int r, int x, int y) {
49     if (l == x && r == y)
50         return sm[a] - sm[b];
51
52     int d = (l + r) >> 1;
53
54     if (y <= d)
55         return query(ls[a], ls[b], l, d, x, y);
56     else if (x > d)
57         return query(rs[a], rs[b], d + 1, r, x, y);
58     else
59         return query(ls[a], ls[b], l, d, x, d) + query(rs[a], rs[b], d + 1, r, d + 1, y);
60 }
61
62 int fa[mxn];
63 int mn[mxn];
64 int mx[mxn];
65
66 int find(int u) {
67     return fa[u] == u ? u : fa[u] = find(fa[u]);
68 }
69
70 int ans = 0;
71
72 inline int lower(int p) {
73     int lt = 1, rt = m, mid, ans = m + 1;
74
75     while (lt <= rt) {
76         mid = (lt + rt) >> 1;
77
78         if (pt[mid].x >= p)
79             rt = mid - 1, ans = mid;
80         else
81             lt = mid + 1;
82     }
83
84     return ans;
85 }
86
87 inline int upper(int p) {
88     int lt = 1, rt = m, mid, ans = 0;
89
90     while (lt <= rt) {
91         mid = (lt + rt) >> 1;
92
93         if (pt[mid].x <= p)
94             lt = mid + 1, ans = mid;
95         else
96             rt = mid - 1;
97     }
98
99     return ans;
100 }
101
102 inline int query(int la, int ra, int lb, int rb) {
103     int st = lower(la);
104     int ed = upper(ra);
105
106     if (st > ed)return 0;
107
108     return query(root[ed], root[st - 1], 1, n, lb, rb);
109 }
110
111 inline void merge(int a, int b) {
112     a = find(a);
113     b = find(b);
114
115     int la = mn[a];
116     int ra = mx[a];
117     int lb = mn[b];
118     int rb = mx[b];
119
120     ans += query(la, ra, lb, rb);
121
122     fa[a] = b;
123     mn[b] = la;
124     mx[b] = rb;
125 }
126
127 signed main(void) {
128 #ifndef ONLINE_JUDGE
129     freopen("in", "r", stdin);
130 #endif
131
132     scanf("%d%d", &n, &m);
133
134     for (int i = 1; i <= n; ++i)
135         scanf("%d", a + i);
136
137     for (int i = 1; i <= m; ++i)
138         scanf("%d%d", &pt[i].x, &pt[i].y);
139
140     std::sort(pt + 1, pt + m + 1, cmp);
141
142     for (int i = 1; i <= m; ++i)
143         insert(root[i], root[i - 1], 1, n, pt[i].y);
144
145     int q, lst = 0;
146
147     for (int i = 1; i <= n; ++i)
148         fa[i] = mn[i] = mx[i] = i;
149
150     for (int i = 1; i <= n; ++i)
151         if (!a[i]) {
152             merge(i, i);
153
154             if (i > 1 && !a[i - 1]
155             && find(i) != find(i - 1))
156                 merge(i - 1, i);
157
158             if (i < n && !a[i + 1]
159             && find(i) != find(i + 1))
160                 merge(i, i + 1);
161         }
162
163     for (scanf("%d", &q); q--; ) {
164         int p; scanf("%d", &p);
165
166         p = (p + lst - 1) % n + 1;
167
168         if (--a[p] == 0)
169         {
170             merge(p, p);
171
172             if (p > 1 && !a[p - 1]
173             && find(p) != find(p - 1))
174                 merge(p - 1, p);
175
176             if (p < n && !a[p + 1]
177             && find(p) != find(p + 1))
178                 merge(p, p + 1);
179         }
180
181         printf("%d\n", lst = ans);
182     }
183 }

UPDATE 这题的做法还真是多啊，放几个链接吧，多多益善嘛~~~

SD_le

Claris

BraketBN

lych_cys

@Author: YouSiki

posted @ 2017-03-12 18:59  YouSiki  阅读(832)  评论(6编辑  收藏  举报