bzoj3052 [wc2013]糖果公园

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3052

http://uoj.ac/problem/58

【题解】

树上莫队+带修改,分块大小n^(2/3)即可。

复杂度O(n^(5/3))

# include <math.h>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 2e5 + 10, N = 1e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

inline int getint() {
    int x = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-') f = 0;
        ch = getchar();
    }
    while(isdigit(ch)) {
        x = (x<<3) + (x<<1) + ch - '0';
        ch = getchar();
    }
    return f ? x : -x;
}

int n, m, Q, V[N], B[N], C[N], t[N];
int head[N], nxt[M], to[M], tot = 0;
inline void add(int u, int v) {
    ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
}
inline void adde(int u, int v) {
    add(u, v), add(v, u);
}

int BLOCK, bl[M];

struct pa {
    int x, y, p, t;
    pa() {}
    pa(int x, int y, int p, int t) : x(x), y(y), p(p), t(t) {}
    friend bool operator < (pa a, pa b) {
        return bl[a.x] < bl[b.x] || (bl[a.x] == bl[b.x] && bl[a.y] < bl[b.y]) ||
               (bl[a.x] == bl[b.x] && bl[a.y] == bl[b.y] && a.t < b.t);
    }
}q[M];

struct paa {
    int x, oc, nc, t;
    paa() {}
    paa(int x, int oc, int nc, int t) : x(x), oc(oc), nc(nc), t(t) {}
}p[M];

int pn, qn;

int beg[N], end[N], dfn[M], DFN = 0;
int fa[N][18], dep[N];
inline void dfs(int x, int fat = 0) {
    beg[x] = ++DFN; dfn[DFN] = x;
    dep[x] = dep[fat] + 1; fa[x][0] = fat;
    for (int i=1; i<=17; ++i) fa[x][i] = fa[fa[x][i-1]][i-1];
    for (int i=head[x]; i; i=nxt[i]) {
        if(to[i] == fat) continue;
        dfs(to[i], x);
    }
    end[x] = ++DFN; dfn[DFN] = x;
}

inline int lca(int u, int v) {
    if(dep[u] < dep[v]) swap(u, v);
    for (int i=17; ~i; --i) if((dep[u] - dep[v]) & (1<<i)) u = fa[u][i];
    if(u == v) return u;
    for (int i=17; ~i; --i) if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
    return fa[u][0];
}

inline bool IN(int L, int R, int x) {
    return L <= x && x <= R;
}

ll ans[M];
bool ban[M];

int ti[M];
ll cnt;
inline void ADD(int c) {
    t[c] ++;
    cnt += (ll)V[c] * B[t[c]];
}

inline void DEL(int c) {
    cnt -= (ll)V[c] * B[t[c]];
    t[c] --;
}

inline void doit(int pos) {
    if(ti[pos] == 0) ADD(C[pos]); 
    else DEL(C[pos]);
    ti[pos] ^= 1;
}

int main() {
    cin >> n >> m >> Q;
    for (int i=1; i<=m; ++i) V[i] = getint();
    for (int i=1; i<=n; ++i) B[i] = getint();
    for (int i=1, u, v; i<n; ++i) {
        u = getint(), v = getint();
        adde(u, v);
    }
    dfs(1); 
    BLOCK = pow(n, 2.0/3.0);
    for (int i=1; i<=DFN; ++i) bl[i] = (i-1)/BLOCK + 1; 
    for (int i=1; i<=n; ++i) t[i] = C[i] = getint(); 
    for (int i=1, o, tx, ty; i<=Q; ++i) {
        o = getint(); tx = getint(), ty = getint();
        if(o) {
            int LCA = lca(tx, ty); 
            if(beg[tx] > beg[ty]) swap(tx, ty);
            if(LCA == tx) q[++qn] = pa(beg[tx], beg[ty], 0, i);
            else q[++qn] = pa(end[tx], beg[ty], LCA, i);
//            cout << LCA << endl;
        } else {
            p[++pn] = paa(tx, t[tx], ty, i);
            t[tx] = ty; ban[i] = 1;
        }
    }
    sort(q+1, q+qn+1);
//    puts("======p======");
//    for (int i=1; i<=pn; ++i) printf("x = %d, oc = %d, nc = %d, t = %d\n", p[i].x, p[i].oc, p[i].nc, p[i].t);
//    puts("======q======");
//    for (int i=1; i<=qn; ++i) printf("x = %d, y = %d, lca = %d, t = %d\n", q[i].x, q[i].y, q[i].p, q[i].t);
//    puts("=============");
    for (int i=1; i<=n; ++i) t[i] = ti[i] = 0;
    int L = 1, R = 0;
    for (int i=1, j=1; i<=qn; ++i) {
        while(j <= pn && q[i].t > p[j].t) {
            if(IN(L, R, beg[p[j].x]) ^ IN(L, R, end[p[j].x])) ADD(p[j].nc), DEL(p[j].oc);
            C[p[j].x] = p[j].nc; ++j;
        }
        while(j-1 >= 1 && q[i].t < p[j-1].t) {
            --j; if(IN(L, R, beg[p[j].x]) ^ IN(L, R, end[p[j].x])) ADD(p[j].oc), DEL(p[j].nc);
            C[p[j].x] = p[j].oc;
        }
//        printf("i = %d, j = %d\n", i, j);
        while(L < q[i].x) doit(dfn[L]), ++L;
        while(L > q[i].x) --L, doit(dfn[L]);
        while(R < q[i].y) ++R, doit(dfn[R]);
        while(R > q[i].y) doit(dfn[R]), --R;
        if(q[i].p) doit(q[i].p);
        ans[q[i].t] = cnt;
        if(q[i].p) doit(q[i].p);    
    }
    for (int i=1; i<=Q; ++i) if(!ban[i]) printf("%lld\n", ans[i]);
    return 0;
}
/*
4 3 5
1 9 2
7 6 5 1
2 3
3 1
3 4
1 2 3 2
1 1 2
1 4 2
0 2 1
1 1 2
1 4 2
*/ 
View Code

 

posted @ 2017-06-15 09:18  Galaxies  阅读(200)  评论(0编辑  收藏  举报