cychester

CF487E Tourists - Tarjan缩点 + 树剖 + multiset

Solution

先Tarjan求出点双联通分量 并缩点。 用$multiset$维护 点双内的最小点权。

容易发现, 点双内的最小点权必须包括与它相连的割边的点权。 所以我们必须想办法来维护。

所以考虑用割点的点权更新它的父节点, 这样查询 点双 内的最小点权只需要查询本身的 $multiset$ 和 它的父亲节点就可以了。

最后加个树剖就能过啦!

Code

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<set>
  5 #include<vector>
  6 #define rd read()
  7 using namespace std;
  8 
  9 const int N = 2e5 + 5;
 10 const int inf = ~0U >> 2;
 11 
 12 int Head[N << 1], Tot;
 13 int head[N], tot;
 14 int low[N], dfn[N], cnt, col, c[N], nd_num, cut[N];
 15 int st[N], tp;
 16 int n, m, Q, a[N];
 17 int f[N << 1], top[N << 1], sz[N << 1], son[N << 1], mk, id[N << 1], dep[N << 1];
 18 
 19 vector<int> q[N];
 20 multiset<int> S[N << 2];
 21 
 22 struct edge {
 23     int nxt, to;
 24 }e[N << 2], E[N << 2];
 25 
 26 int read() {
 27     int X = 0, p = 1; char c = getchar();
 28     for (; c > '9' || c < '0'; c = getchar()) 
 29         if (c == '-') p = -1;
 30     for (; c >= '0' && c <= '9'; c = getchar())
 31         X = X * 10 + c - '0';
 32     return X * p;
 33 }
 34 
 35 void add(int u, int v) {
 36     e[++tot].to = v;
 37     e[tot].nxt = head[u];
 38     head[u] = tot;
 39 }
 40 
 41 void Add(int u, int v) {
 42     E[++Tot].to = v;
 43     E[Tot].nxt = Head[u];
 44     Head[u] = Tot;
 45 }
 46 
 47 void tarjan(int u) {
 48     low[u] = dfn[u] = ++cnt;
 49     st[++tp] = u;
 50     int flag = 0;
 51     for (int i = head[u]; i; i = e[i].nxt) {
 52         int nt = e[i].to;
 53         if (!dfn[nt]) {
 54             tarjan(nt);
 55             low[u] = min(low[u], low[nt]);
 56             if (low[nt] < dfn[u]) 
 57                 continue;
 58             col++; flag++;
 59             cut[u] = 1;
 60             for (; tp;) {
 61                 int z = st[tp--];
 62                 q[col].push_back(z);
 63                 if (z == nt)
 64                     break;
 65             }
 66             q[col].push_back(u);
 67         }
 68         else low[u] = min(low[u], dfn[nt]);
 69     }
 70     if (flag < 2 && u == 1)
 71         cut[u] = 0;
 72 }
 73 
 74 namespace SegT {
 75 
 76     int MIN[N << 3];
 77 
 78 #define mid ((l + r) >> 1)
 79 #define lson nd << 1
 80 #define rson nd << 1 | 1
 81     
 82     void up(int nd) {
 83         MIN[nd] = min(MIN[lson], MIN[rson]);
 84     }
 85 
 86     void modify(int pos, int d, int l, int r, int nd) {
 87         if (l == r) {
 88             MIN[nd] = d;
 89             return;
 90         }
 91         if (pos <= mid)
 92             SegT::modify(pos, d, l, mid, lson);
 93         else
 94             SegT::modify(pos, d, mid + 1, r, rson);
 95         SegT::up(nd);
 96     }
 97     int query(int L, int R, int l, int r, int nd) {
 98         if (L <= l && r <= R)
 99             return MIN[nd];
100         int tmp = inf;
101         if(L <= mid)
102             tmp = min(tmp, SegT::query(L, R, l, mid, lson));
103         if(mid < R)
104             tmp = min(tmp, SegT::query(L, R, mid + 1, r, rson));
105         return tmp;
106     }
107 
108 #undef mid
109 #undef lson
110 #undef rson
111 }
112 
113 namespace SP {
114 
115     void dfs1(int u) {
116         sz[u] = 1;
117         for (int i = Head[u]; i; i = E[i].nxt) {
118             int nt = E[i].to;
119             if (nt == f[u])
120                 continue;
121             f[nt] = u;
122             dep[nt] = dep[u] + 1;
123             SP::dfs1(nt);
124             sz[u] += sz[nt];
125             if(sz[nt] >= sz[son[u]])
126                 son[u] = nt;
127         }
128     }
129 
130     void dfs2(int u) {
131         id[u] = ++mk;
132         if (!son[u])
133             return;
134         top[son[u]] = top[u];
135         SP::dfs2(son[u]);
136         for (int i = Head[u]; i; i = E[i].nxt) {
137             int nt = E[i].to;
138             if (nt == f[u] || nt == son[u])
139                 continue;
140             top[nt] = nt;
141             SP::dfs2(nt);
142         }
143     }
144 
145     int query(int x, int y) {
146         int re = inf, tmp;
147         for (; top[x] != top[y];) {
148             if (dep[top[x]] < dep[top[y]])
149                 swap(x, y);
150             tmp = SegT::query(id[top[x]], id[x], 1, mk, 1);
151             re = min(tmp, re);
152             x = f[top[x]];
153         }
154         if (dep[x] < dep[y])
155             swap(x, y);
156         tmp = SegT::query(id[y], id[x], 1, mk, 1);
157         re = min(tmp, re);
158         if (f[y] && y <= col)
159             tmp = SegT::query(id[f[y]], id[f[y]], 1, mk, 1);
160         re = min(tmp, re);
161         return re;
162     }
163 }
164 
165 int main()
166 {
167     n = rd; m = rd; Q = rd;
168     for (int i = 1; i <= n; ++i)
169         a[i] = rd;
170     for (int i = 1; i <= m; ++i) {
171         int u = rd, v = rd;
172         add(u, v); add(v, u);
173     }
174     tarjan(1);
175     nd_num = col;
176     for (int i = 1; i <= n; ++i)
177         if (cut[i]) c[i] = ++nd_num;
178     for (int i = 1; i <= col; ++i)
179         for (int j = 0, len = q[i].size(); j < len; ++j) {
180             int x = q[i][j];
181             if (cut[x])
182                 Add(c[x], i), Add(i, c[x]);
183             else c[x] = i;
184         }
185     dep[1] = 1;
186     SP::dfs1(1);
187     top[1] = 1;
188     SP::dfs2(1);
189     for (int i = 1; i <= n; ++i) {
190         int x = c[i];
191         S[x].insert(a[i]);
192         if(x > col)
193             S[f[x]].insert(a[i]);
194     }
195     for (int i = 1; i <= nd_num; ++i) {
196         int x = *S[i].begin();
197         SegT::modify(id[i], x, 1, mk, 1);
198     }
199     for (; Q; Q--) {
200         char ch = getchar();
201         while (ch != 'A' && ch != 'C')
202             ch = getchar();
203         int u = rd, v = rd;
204         if (ch == 'C') {
205             swap(v, a[u]);
206             S[c[u]].erase(S[c[u]].find(v));
207             S[c[u]].insert(a[u]);
208             int x = *S[c[u]].begin();
209             SegT::modify(id[c[u]], x, 1, mk, 1);
210             if (c[u] <= col)
211                 continue;
212             S[f[c[u]]].erase(S[f[c[u]]].find(v));
213             S[f[c[u]]].insert(a[u]);
214             x = *S[f[c[u]]].begin();
215             SegT::modify(id[f[c[u]]], x, 1, mk, 1);
216         }
217         else {
218             if (u == v) printf("%d\n", a[u]);
219             else printf("%d\n", SP::query(c[u], c[v]));
220         }
221     }
222 }
View Code

 

posted on 2018-09-19 21:09  cychester  阅读(163)  评论(0编辑  收藏  举报

导航