• bzoj2333 [SCOI2011]棘手的操作


    题目

    bzoj2333

    题解

    联通块合后并不需要再拆开,可以考虑离线做法

    想办法将各个点按联通块有序排列,接下来就直接用线段树区间维护即可

    fa[i] 记录 i 所处联通块的起始点

    ed[i] 记录 以i为起始点 的联通块的终止点

    nt[i] 记录 i 的下一个节点

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 300005;
    
    int n, Q, a[N];
    int dfn[N], w[N], t;
    int fa[N], nt[N], ed[N];
    
    inline int read()
    {
        int x = 0, f = 1; char ch = getchar();
        while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
        return x * f;
    }
    
    struct node
    {
        int op, x, y;
    }q[N];
    
    struct tree
    {
        int l, r, d, mx;
    }T[N << 3];
    
    int findf(int x)
    {
        if(x == fa[x]) return x;
        return fa[x] = findf(fa[x]);
    }
    
    void init()
    {
        n = read();
        for(int i = 1; i <= n; i++) a[i] = read(), fa[i] = ed[i] = i;
        Q = read();
        for(int i = 1; i <= Q; i++)
        {
            char s[10]; scanf("%s", s);        
            if(s[0] == 'U')
            {
                int x = read(), y = read();
                q[i].op = 1; q[i].x = x; q[i].y = y;
                x = findf(x); y = findf(y);
                if(x == y) continue; 
                fa[y] = x;
                nt[ed[x]] = y;
                ed[x] = ed[y];
            }
            else if(s[0] == 'A')
            {
                if(s[1] == '1') {q[i].op = 2; q[i].x = read(); q[i].y = read();}
                else if(s[1] == '2') {q[i].op = 3; q[i].x = read(); q[i].y = read();}
                else {q[i].op = 4; q[i].x = read();}
            }
            else
            {
                if(s[1] == '1') {q[i].op = 5; q[i].x = read();}
                else if(s[1] == '2') {q[i].op = 6; q[i].x = read();}
                else q[i].op = 7;
            }
        }
    }
    
    void get_id()
    {
        for(int i = 1; i <= n; i++)
            if(findf(i) == i)
            {
                for(int j = i; findf(j) == i; j = nt[j])
                    {dfn[j] = ++t; w[t] = a[j];} 
            }
    }
    
    void pushup(int p) {T[p].mx = max(T[p << 1].mx, T[p << 1 | 1].mx);} 
    
    void pushdown(int p)
    {
        if(!T[p].d) return;
        T[p << 1].d += T[p].d; T[p << 1].mx += T[p].d;
        T[p << 1 | 1].d += T[p].d; T[p << 1 | 1].mx += T[p].d;
        T[p].d = 0;
    }
    
    void build(int p, int x, int y)
    {
        T[p].l = x; T[p].r = y;
        if(x == y) {T[p].mx = w[x]; return;}
        int mid = (x + y) >> 1;
        build(p << 1, x, mid); build(p << 1 | 1, mid + 1, y);
        pushup(p);
    }
    
    void update(int p, int x, int y, int v)
    {
        int pl = T[p].l, pr = T[p].r;
        if(pl == x && pr == y) {T[p].d += v; T[p].mx += v; return;}
        pushdown(p); 
        int mid = (pl + pr) >> 1; 
        if(y <= mid) update(p << 1, x, y, v);
        else if(x > mid) update(p << 1 | 1, x, y, v);
        else {update(p << 1, x, mid, v); update(p << 1 | 1, mid + 1, y, v);}
        pushup(p);
    }
    
    int query_max(int p, int x, int y)
    {
        int pl = T[p].l, pr = T[p].r;
        if(pl == x && pr == y) return T[p].mx;
        pushdown(p); 
        int mid = (pl + pr) >> 1;
        if(y <= mid) return query_max(p << 1, x, y);
        else if(x > mid) return query_max(p << 1 | 1, x, y);
        else return max(query_max(p << 1, x, mid), query_max(p << 1 | 1, mid + 1, y)); 
    }
    
    void solve()
    {
        for(int i = 1; i <= n; i++) fa[i] = ed[i] = i;
        
        for(int i = 1; i <= Q; i++)
        {
            int x = q[i].x, y = q[i].y;
            if(q[i].op == 1)
            {
                x = findf(x); y = findf(y);
                if(x == y) continue;
                fa[y] = x; ed[x] = ed[y];
            }
            else if(q[i].op == 2) update(1, dfn[x], dfn[x], y);
            else if(q[i].op == 3) update(1, dfn[findf(x)], dfn[ed[findf(x)]], y);
            else if(q[i].op == 4) update(1, 1, n, x);
            else if(q[i].op == 5) printf("%d
    ", query_max(1, dfn[x], dfn[x]));
            else if(q[i].op == 6) printf("%d
    ", query_max(1, dfn[findf(x)], dfn[ed[findf(x)]]));
            else printf("%d
    ", query_max(1, 1, n));
        }
        	
    }
    
    int main()
    {
        init();
        get_id();
        build(1, 1, n);
        solve();
        return 0;
    }
  • 相关阅读:
    当老板如何带团队?
    创业者第一法宝-了解自己
    交流才能交易,交易才能交心
    集合框架
    MySQL一些命令语法
    JS组成整理
    git中可以pull但是push提示Everything up-to-date的情况
    循环判断以及文件的使用--练习1
    Hello World !
    linux文件权限修改
  • 原文地址:https://www.cnblogs.com/XYZinc/p/8930911.html
Copyright © 2020-2023  润新知