[CTSC2008]網絡管理 [整體二分]
阿新 • • 發佈:2019-04-05
ctsc2008 str swa main string cst efi continue top
題面
bzoj
luogu
所有事件按時間排序
按值劃分下放
把每一個修改
改成一個刪除一個插入
對於一個查詢
直接查這個段區間有多少合法點
如果查詢值大於等於目標值 進入左區間
如果一個查詢無解
那麽它要求第k大無解
k > 路徑長 用lca維護即可
#include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #define Sqr(x) ((x)*(x)) using namespace std; const int N = 8e4 + 5; const int inf = 1e8 + 5; struct Edge{ int v, next; }edge[N << 1]; int head[N], esize; inline void addedge(int x, int y){ edge[++esize] = (Edge){y, head[x]}; head[x] = esize; } struct Node{ int t, x, y, w, d; bool type; //0是插入 1是查詢 }node[N << 2], p1[N << 2], p2[N << 2]; int n, m, nsize, a[N], ans[N]; int tim, dfn[N], top[N], son[N], fa[N], size[N], rf[N], dep[N]; bool flag[N]; struct BIT{ int w[N]; void ins(int x, int d){while(x <= n){w[x] += d; x += x & -x;}} int qry(int x){int res = 0; while(x){res += w[x]; x -= x & -x;} return res;} }bit; inline void addnode(int x1, int x2, int x3, int x4, int x5, bool x6){ ++nsize, node[nsize].t = x1, node[nsize].x = x2, node[nsize].y = x3, node[nsize].w = x4, node[nsize].d = x5, node[nsize].type = x6; } void dfs1(int x, int ff){ dep[x] = dep[ff] + 1, size[x] = 1, fa[x] = ff; for(int i = head[x], vv; ~i; i = edge[i].next){ vv = edge[i].v; if(vv == ff) continue; dfs1(vv, x); size[x] += size[vv]; if(size[son[x]] < size[vv]) son[x] = vv; } } void dfs2(int x, int tp){ top[x] = tp, dfn[x] = ++tim, rf[tim] = x; if(son[x]) dfs2(son[x], tp); else return; for(int i = head[x], vv; ~i; i = edge[i].next){ vv = edge[i].v; if(vv == fa[x] || vv == son[x]) continue; dfs2(vv, vv); } } int LCA(int x, int y){ while(top[x] != top[y]){ if(dep[top[x]] < dep[top[y]]) swap(x, y); x = fa[top[x]]; } return dep[x] < dep[y] ? x : y; } int qry(int x, int y){ int res = 0; while(top[x] != top[y]){ if(dep[top[x]] < dep[top[y]]) swap(x, y); res += bit.qry(dfn[x]) - bit.qry(dfn[top[x]] - 1); x = fa[top[x]]; } if(dep[x] < dep[y]) swap(x, y); res += bit.qry(dfn[x]) - bit.qry(dfn[y] - 1); return res; } void erfn(int L, int R, int l, int r){ if(L > R) return; if(l == r){ for(int i = L; i <= R; ++i) if(node[i].type && ~ans[node[i].t]) ans[node[i].t] = l; return ; } int mid = l + ((r - l) >> 1); int t1 = 0, t2 = 0; for(int i = L; i <= R; ++i){ if(node[i].type) { int cnt = qry(node[i].x, node[i].y); if(cnt >= node[i].w) p2[++t2] = node[i]; else node[i].w -= cnt, p1[++t1] = node[i];//第k大!!先減再復制!! } else { if(node[i].w <= mid) p1[++t1] = node[i]; else p2[++t2] = node[i], bit.ins(dfn[node[i].x], node[i].d); } } for(int i = L; i <= R; ++i) if(!node[i].type && node[i].w > mid) bit.ins(dfn[node[i].x], -node[i].d); for(int i = 1; i <= t1; ++i) node[L + i - 1] = p1[i]; for(int i = 1; i <= t2; ++i) node[L + t1 + i - 1] = p2[i]; erfn(L, L + t1 - 1, l, mid); erfn(L + t1, R, mid + 1, r); } int main() { memset(head, -1, sizeof(head)); scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i){ scanf("%d", &a[i]); addnode(0, i, 0, a[i], 1, 0); } for(int i = 1, x, y; i < n; ++i){ scanf("%d%d", &x, &y); addedge(x, y); addedge(y, x); } dfs1(1, 0); dfs2(1, 1); for(int i = 1, x, y, z; i <= m; ++i){ scanf("%d%d%d", &x, &y, &z); flag[i] = (bool)x; if(x){ int len = dep[y] + dep[z] - 2 * dep[LCA(y, z)] + 1; if(x > len) ans[i] = -1; else addnode(i, y, z, x, 0, 1); } else addnode(i, y, 0, a[y], -1, 0), addnode(i, y, 0, z, 1, 0), a[y] = z, ans[i] = -1; } erfn(1, nsize, 0, inf); for(int i = 1; i <= m; ++i) if(flag[i]){ if(ans[i] == -1) printf("invalid request!\n"); else printf("%d\n", ans[i]); } //system("PAUSE"); return 0; }
[CTSC2008]網絡管理 [整體二分]