bzoj2333 [SCOI2011] tricky operations

topic

bzoj2333

answer

After the Unicom block is closed, it does not need to be disassembled, and offline methods can be considered.

Find a way to arrange the points in an orderly manner according to the Unicom block, and then use the line segment tree interval to maintain it directly.

fa[i] records the starting point of the connection block where i is located

ed[i] records the end point of the connected block with i as the starting point

nt[i] records the next node of 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\n", query_max(1, dfn[x], dfn[x]));
        else if(q[i].op == 6) printf("%d\n", query_max(1, dfn[findf(x)], dfn[ed[findf(x)]]));
        else printf("%d\n", query_max(1, 1, n));
    }
        
}

int main()
{
    init();
    get_id();
    build(1, 1, n);
    solve();
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324766306&siteId=291194637