• 【题解】HNOI2016网络


      整体二分是个好东西!可我忘记了它QAQ其实当你知道这题可以整体二分的时候就已经不难了(个人觉得这是最难想到的一点啊)。整体二分的话,我们就可以把问题转化为是否有一条权值 (>= k) 的链经过某一点,这个可以通过树上差分做到 (logn) 的复杂度。而由于每次二分答案之后,都可以将询问和操作分成两个部分,所以是满足整体二分的性质的。

      以及自己的代码能力还有待提升啊……(;д;)

    #include <bits/stdc++.h>
    using namespace std;
    #define lowbit(i) (i & (-i))
    #define maxn 1000000
    #define INF 99999999
    #define CNST 20
    int n, m, tot, book[maxn];
    int b[maxn], id[maxn];
    int C[maxn], Ans[maxn], pos[maxn];
    int dfn[maxn], size[maxn], f[maxn];
    int timer, cnt, ST[maxn * 2][CNST];
    int bit[CNST], Log[maxn * 2];
    map <int, int> Map;
    
    int read()
    {
        int x = 0, k = 1;
        char c; c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    struct node
    {
        int opt, x, y, w, mark, id, rec;
    }Q[maxn], ql[maxn], qr[maxn];
    
    struct edge
    {
        int cnp, to[maxn], last[maxn], head[maxn];
        edge() { cnp = 1; }
        void add(int u, int v)
        {
            to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
            to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;
        }
    }E1;
    
    void Update(int x, int y) 
    { 
        if(!x) return;
        for(; x <= n; x += lowbit(x)) C[x] += y; 
    }
    
    int Query(int x)
    {
        int ret = 0;
        for(; x; x -= lowbit(x)) ret += C[x];
        return ret;
    }
    
    void dfs(int u, int fa)
    {
        dfn[u] = ++ timer; size[u] = 1; f[dfn[u]] = dfn[fa];
        ST[++ cnt][0] = dfn[u]; pos[u] = cnt;
        for(int i = E1.head[u]; i; i = E1.last[i])
        {
            int v = E1.to[i];
            if(v == fa) continue;
            dfs(v, u); size[u] += size[v];
            ST[++ cnt][0] = dfn[u];
        }
    }
    
    int RMQ(int u, int v)
    {
        u = pos[u], v = pos[v];
        if(u > v) swap(u, v);
        int k = Log[v - u + 1];
        return min(ST[u][k], ST[v - bit[k] + 1][k]);
    }
    
    void Check(int l, int r, int ll, int rr)
    {
        if(l == r)
        {
            for(int i = ll; i <= rr; i ++)
                if(Q[i].opt == 2) 
                    Ans[Q[i].id] = l ? id[l] : -1;
            return;
        }
        if(l > r) return;
        int mid = (l + r) >> 1, sum = 0;
        for(int i = ll; i <= rr; i ++)
        {
            int x = Q[i].x, y = Q[i].y;
            if(!Q[i].opt && Q[i].rec > mid)
            {
                Update(dfn[x], 1), Update(dfn[y], 1);
                int K = RMQ(x, y);
                Update(K, -1), Update(f[K], -1); sum ++;
            }
            else if(Q[i].opt == 1 && Q[i].rec > mid) 
            {
                Update(dfn[x], -1), Update(dfn[y], -1);
                int K = RMQ(x, y);
                Update(K, 1), Update(f[K], 1); sum --;
            }
            else if(Q[i].opt == 2)
            {
                int x = Query(dfn[Q[i].x] + size[Q[i].x] - 1) - Query(dfn[Q[i].x] - 1);
                if(x < sum) Q[i].mark = 1;
            }
        }
        for(int i = ll; i <= rr; i ++)
        {
            int x = Q[i].x, y = Q[i].y;
            if(!Q[i].opt && Q[i].rec > mid && !book[Q[i].id])
            {
                Update(dfn[x], -1), Update(dfn[y], -1);
                int K = RMQ(x, y);
                Update(K, 1), Update(f[K], 1);
            }
        }
        int L = 0, R = 0;
        for(int i = ll; i <= rr; i ++)
        {
            if(Q[i].opt == 2) 
            {
                if(Q[i].mark) Q[i].mark = 0, qr[++ R] = Q[i];
                else ql[++ L] = Q[i];
            }
            else if(Q[i].rec > mid) qr[++ R] = Q[i]; 
            else ql[++ L] = Q[i];
        }
        int rec = ll - 1, ls = 1, rs = 1;
        while(ls <= L) Q[++ rec] = ql[ls], ls ++;
        while(rs <= R) Q[++ rec] = qr[rs], rs ++;
        
        Check(l, mid, ll, ll + ls - 2);
        Check(mid + 1, r, ll + ls - 1, rr);
    }
    
    void init()
    {
        bit[0] = 1; for(int i = 1; i < CNST; i ++) bit[i] = bit[i - 1] << 1;
        Log[0] = -1; for(int i = 1; i < maxn * 2; i ++) Log[i] = Log[i >> 1] + 1;
    }
    
    int main()
    {
        init();
        n = read(), m = read();
        for(int i = 1; i <= m; i ++) Ans[i] = -INF;
        for(int i = 1; i < n; i ++)
        {
            int u = read(), v = read();
            E1.add(u, v);
        }
        dfs(1, 0);
        for(int i = 1; i <= Log[cnt]; i ++)
            for(int j = 1; j + bit[i - 1] <= cnt; j ++)
                ST[j][i] = min(ST[j][i - 1], ST[j + bit[i - 1]][i - 1]);
        for(int i = 1; i <= m; i ++)
        {
            Q[i].opt = read(); Q[i].id = i; 
            if(Q[i].opt == 0) 
            {
                Q[i].x = read(), Q[i].y = read(), Q[i].w = read();
                b[++ tot] = Q[i].w;
            }
            else if(Q[i].opt == 1)
            {
                int t = read(); book[t] = 1;
                Q[i] = Q[t], Q[i].opt = 1;  Q[i].id = i;
            }
            else if(Q[i].opt == 2) Q[i].x = read();
        }
        sort(b + 1, b + 1 + tot); int tem = 0;
        for(int i = 1; i <= tot; i ++)
            if(b[i] != b[i - 1]) Map[b[i]] = ++ tem, id[tem] = b[i];
        tot = tem;
        for(int i = 1; i <= m; i ++)
            if(!Q[i].opt || Q[i].opt == 1) Q[i].rec = Map[Q[i].w];
        Check(0, tot, 1, m);
        for(int i = 1; i <= m; i ++)
            if(Ans[i] != -INF) printf("%d
    ", Ans[i]);
        return 0;
    }
  • 相关阅读:
    codeforce 1478B B. Nezzar and Lucky Number 找规律 打表 C
    codeforce 1478C C. Nezzar and Symmetric Array 模拟 认真写 C
    Ansible自动化入门
    多线程执行传值
    js 文本框根据开始结束符号控制输入内容(IE)
    update where in 子查询的梗
    Qt中的QThread:使用QSemaphore进行多线程数据同步
    linux服务器下CPU爆满
    linux下磁盘爆满问题排查
    每日一题(算法)
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/9571726.html
Copyright © 2020-2023  润新知