bzoj 4849 Mole Tunnels

模拟费用流.

模拟费用流是怎么回事呢?模拟相信大家都很熟悉,但是模拟费用流是怎么回事呢,下面就让小编带大家一起了解吧.

模拟费用流,其实就是模拟费用流的过程,大家可能会很惊讶,模拟怎么会费用流呢?

但事实就是这样,小编也感到非常惊讶.

这就是关于模拟费用流的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
//%std
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read()
{
int out = 0, fh = 1;
char jp = getchar();
while ((jp > '9' || jp < '0') && jp != '-')
jp = getchar();
if (jp == '-')
fh = -1, jp = getchar();
while (jp >= '0' && jp <= '9')
out = out * 10 + jp - '0', jp = getchar();
return out * fh;
}
const int N = 1e5 + 10, inf = 1e9;
int n, m, c[N], ans = 0, idx = 0, st[N], ed[N], rnk[N], dep[N];
void dfs(int x)
{
st[x] = ++idx, rnk[idx] = x;
if (2 * x <= n)
{
dep[2 * x] = dep[x] + 1;
dfs(2 * x);
}
if (2 * x + 1 <= n)
{
dep[2 * x + 1] = dep[x] + 1;
dfs(2 * x + 1);
}
ed[x] = idx;
}
struct node
{
int mi, mi_real, tag, pos;
} Tree[N << 2];
#define root Tree[o]
#define lson Tree[o << 1]
#define rson Tree[o << 1 | 1]
void pushup(int o)
{
root.mi = min(lson.mi, rson.mi);
root.mi_real = min(lson.mi_real, rson.mi_real);
if (lson.mi < rson.mi)
root.pos = lson.pos;
else
root.pos = rson.pos;
}
void BuildTree(int o, int l, int r)
{
if (l == r)
{
root.mi = c[rnk[l]] ? dep[rnk[l]] : inf;
root.mi_real = dep[rnk[l]];
root.pos = rnk[l];
return;
}
int mid = (l + r) >> 1;
BuildTree(o << 1, l, mid);
BuildTree(o << 1 | 1, mid + 1, r);
pushup(o);
}
void modify(int o, int c)
{
root.mi += c;
if (c < inf)
root.mi_real += c;
root.tag += c;
}
void pushdown(int o)
{
if (root.tag)
{
modify(o << 1, root.tag);
modify(o << 1 | 1, root.tag);
root.tag = 0;
}
}
void upd(int o, int l, int r, int L, int R, int c)
{
if (L <= l && r <= R)
return modify(o, c);
int mid = (l + r) >> 1;
pushdown(o);
if (L <= mid)
upd(o << 1, l, mid, L, R, c);
if (R > mid)
upd(o << 1 | 1, mid + 1, r, L, R, c);
pushup(o);
}
void query(int &pos, int &mi, int o, int l, int r, int L, int R)
{
if (L <= l && r <= R)
{
if (root.mi < mi)
mi = root.mi, pos = root.pos;
return;
}
pushdown(o);
int mid = (l + r) >> 1;
if (L <= mid)
query(pos, mi, o << 1, l, mid, L, R);
if (R > mid)
query(pos, mi, o << 1 | 1, mid + 1, r, L, R);
}
int query_real(int o, int l, int r, int pos)
{
if (l == r)
return root.mi_real;
pushdown(o);
int mid = (l + r) >> 1;
if (pos <= mid)
return query_real(o << 1, l, mid, pos);
else
return query_real(o << 1 | 1, mid + 1, r, pos);
}
int up[N], down[N]; // available flow of inverse edge
int main()
{
n = read(), m = read();
dfs(1);
for (int i = 1; i <= n; ++i)
c[i] = read();
BuildTree(1, 1, n);
while (m--)
{
int x = read(), lca = x, mi, tmp, d = 0, dis = inf, y, p;
while (lca)
{
mi = inf;
query(tmp, mi, 1, 1, n, st[lca], ed[lca]);
if (mi < inf)
{
int k = d + mi - query_real(1, 1, n, st[lca]);
if (k < dis)
dis = k, y = tmp, p = lca;
}
d += up[lca] ? -1 : 1;
lca >>= 1;
}
ans += dis;
printf("%d ", ans);

--c[y];
if (!c[y])
upd(1, 1, n, st[y], st[y], inf);
lca = p;

// x -> lca
p = x;
while (p != lca)
{
if (up[p]) // used inverse edge
--up[p];
else // not
{
++down[p];
if (down[p] == 1) // cost : 1 -> -1
upd(1, 1, n, st[p], ed[p], -2);
}
p >>= 1;
}

// lca -> y
p = y;
while (p != lca)
{
if (down[p]) // used inverse edge
{
--down[p];
if (down[p] == 0) // cost : -1 -> 1
upd(1, 1, n, st[p], ed[p], 2);
}
else // not
++up[p];
p >>= 1;
}
}
return 0;
}