zoukankan      html  css  js  c++  java
  • 「CTSC2008」网络管理

    「CTSC2008」网络管理

    传送门
    整体二分做法,应该和这题一样的吧。
    就是把序列换成树,第 (k) 小换成第 (k) 大。
    然后就切了。。。
    参考代码:

    #include <algorithm>
    #include <cstdio>
    #define rg register
    #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
    using namespace std;
    template < class T > inline void read(T& s) {
        s = 0; int f = 0; char c = getchar();
        while ('0' > c || c > '9') f |= c == '-', c = getchar();
        while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
        s = f ? -s : s;
    }
    
    const int _ = 80005;
    
    int tot, head[_]; struct Edge { int ver, nxt; } edge[_ << 1];
    inline void Add_edge(int u, int v) { edge[++tot] = (Edge) { v, head[u] }, head[u] = tot; }
    
    int n, m, a[_], ans[_], tr[_];
    int num, q; struct node { int k, x, y, id; } t[_ << 1], tt1[_ << 1], tt2[_ << 1];
    int dep[_], siz[_], son[_], fa[_], dfn[_], top[_];
    
    inline void update(int x, int v) { for (rg int i = x; i <= n; i += i & -i) tr[i] += v; }
    
    inline int query(int x) { int res = 0; for (rg int i = x; i >= 1; i -= i & -i) res += tr[i]; return res; }
    
    inline int Query(int x, int y) {
        int fx = top[x], fy = top[y], res = 0;
        while (fx != fy) {
        	if (dep[fx] < dep[fy]) swap(x, y), swap(fx, fy);
        	res += query(dfn[x]) - query(dfn[fx] - 1), x = fa[fx], fx = top[x];
        }
        if (dep[x] > dep[y]) swap(x, y);
        res += query(dfn[y]) - query(dfn[x] - 1);
        return res;
    }
    
    inline void dfs(int u, int f) {
        dep[u] = dep[f] + 1, siz[u] = 1, fa[u] = f;
        for (rg int i = head[u]; i; i = edge[i].nxt) {
        	int v = edge[i].ver; if (v == f) continue ;
        	dfs(v, u), siz[u] += siz[v];
        	if (siz[son[u]] < siz[v]) son[u] = v;
        }
    }
    
    inline void dfs(int u, int f, int topf) {
        dfn[u] = ++dfn[0], top[u] = topf;
        if (son[u]) dfs(son[u], u, topf);
        for (rg int i = head[u]; i; i = edge[i].nxt) {
    	    int v = edge[i].ver; if (v == f || v == son[u]) continue ;
    	    dfs(v, u, v);
        }
    }
    
    inline void solve(int ql, int qr, int l, int r) {
        if (ql > qr || l > r) return ;
        if (l == r) { for (rg int i = ql; i <= qr; ++i) if (t[i].id) ans[t[i].id] = l; return ; }
        int mid = (l + r) >> 1, p1 = 0, p2 = 0;
        for (rg int i = ql; i <= qr; ++i) {
    	    if (t[i].id == 0) {
        	    if (t[i].y <= mid) tt1[++p1] = t[i]; else update(dfn[t[i].x], t[i].k), tt2[++p2] = t[i];
        	} else {
    	        int cnt = Query(t[i].x, t[i].y);
    	        if (cnt < t[i].k) t[i].k -= cnt, tt1[++p1] = t[i]; else tt2[++p2] = t[i];
    	    }
        }
        for (rg int i = 1; i <= p2; ++i) if (tt2[i].id == 0) update(dfn[tt2[i].x], -tt2[i].k);
        for (rg int i = 1; i <= p1; ++i) t[ql + i - 1] = tt1[i];
        for (rg int i = 1; i <= p2; ++i) t[ql + p1 + i - 1] = tt2[i];
        solve(ql, ql + p1 - 1, l, mid), solve(ql + p1, qr, mid + 1, r);
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        file("cpp");
    #endif
        read(n), read(m);
        for (rg int i = 1; i <= n; ++i) read(a[i]), t[++num] = (node) { 1, i, a[i], 0 };
        for (rg int u, v, i = 1; i < n; ++i) read(u), read(v), Add_edge(u, v), Add_edge(v, u);
        dfs(1, 0), dfs(1, 0, 1);
        for (rg int k, x, y, i = 1; i <= m; ++i) {
    	    read(k), read(x), read(y);
    	    if (k == 0) {
        	    t[++num] = (node) { -1, x, a[x], 0 };
    	        t[++num] = (node) { 1, x, a[x] = y, 0 };
    	    } else
        	    t[++num] = (node) { k, x, y, ++q };
        }
        solve(1, num, 0, 100000000);
        for (rg int i = 1; i <= q; ++i) if (ans[i] == 0) puts("invalid request!"); else printf("%d
    ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    URAL 2067 Friends and Berries (推理,数学)
    URAL 2070 Interesting Numbers (找规律)
    URAL 2073 Log Files (模拟)
    URAL 2069 Hard Rock (最短路)
    URAL 2068 Game of Nuts (博弈)
    URAL 2066 Simple Expression (水题,暴力)
    URAL 2065 Different Sums (找规律)
    UVa 1640 The Counting Problem (数学,区间计数)
    UVa 1630 Folding (区间DP)
    UVa 1629 Cake slicing (记忆化搜索)
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12246913.html
Copyright © 2011-2022 走看看