• P4074 [WC2013]糖果公园


    P4074 WC2013糖果公园
    树上带修莫队(欧拉序分块,特判lca),然后,,,我排序错了,T了一页。。。
    为了过都没用递归。。。修改就按他说的修改就行。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    
    using namespace std;
    
    typedef long long ll;
    const ll MAXN = 1e6+10;
    
    ll N, M, seq[MAXN], Q, head[MAXN], cnt = -1, C[MAXN], V[MAXN], W[MAXN], block[MAXN], tst[MAXN], tem[MAXN];
    ll in[MAXN], out[MAXN], num, dep[MAXN], fa[22][MAXN], tim, chacnt, len, tot, pos[2][MAXN], vis[MAXN];
    ll SIZ;
    
    struct edg {ll nt, to;} E[MAXN];
    struct ask {
        ll x, y, id, flag, la;
    	friend bool operator < (ask a, ask b) {return block[a.x] == block[b.x] ? block[a.y] == block[b.y] ? a.id < b.id : block[a.y] < block[b.y] : block[a.x] < block[b.x];}
    } A[MAXN];
    struct cha {ll x, y, tim;} CH[MAXN];
    
    void add(ll, ll);
    void dfs(ll, ll);
    ll lca(ll, ll);
    
    int main() {
        //freopen("P4074_1.in", "r", stdin);
        memset(head, -1, sizeof(head));
        scanf("%lld%lld%lld", &N, &M, &Q);
        SIZ = (ll)pow(N, 2.0 / 3.0);
        for (ll i = 1; i <= M; i++) scanf("%lld", V+i);
        for (ll i = 1; i <= N; i++) scanf("%lld", W+i);
        for (ll i = 1, x, y; i < N; i++) scanf("%lld%lld", &x, &y),add(x, y),add(y, x);
        for (ll i = 1; i <= N; i++) scanf("%lld", C+i);
        dfs(1, 0);
        for (ll i = 1, kind, x, y; i <= Q; i++) {
            scanf("%lld%lld%lld", &kind, &x, &y);
            if (kind) {
                if (in[x] > in[y]) swap(x, y);
                if (lca(x, y) == x) tim++, A[tim] = {pos[0][x], pos[0][y], tim, 0, 0};
                else tim++, A[tim] = {pos[1][x], pos[0][y], tim, 1, lca(x, y)};
            } else CH[++chacnt] = {x, y, tim};
        }
        for (ll i = 1; i <= 2*N; i++) {
            if (i % SIZ == 1) tot++;
            block[i] = tot;
        }
        ll now = 0, ans = 0, l = 1, r = 0; sort(A+1, A+tim+1); CH[chacnt+1].tim = 0x3f3f3f3f3f3f3f3f;
        for (ll i = 1; i <= tim; i++) {
            while (CH[now].tim < A[i].id && now <= chacnt) {
            	now++;
    		    if (vis[CH[now].x] == 1) ans -= (V[C[CH[now].x]] * W[tst[C[CH[now].x]]--]);
                swap(CH[now].y, C[CH[now].x]);
                if (vis[CH[now].x] == 1) ans += (V[C[CH[now].x]] * W[++tst[C[CH[now].x]]]);
            }
            while (A[i].id <= CH[now].tim && now >= 1) {
                if (vis[CH[now].x] == 1) ans -= (V[C[CH[now].x]] * W[tst[C[CH[now].x]]--]);
                swap(CH[now].y, C[CH[now].x]);
                if (vis[CH[now].x] == 1) ans += (V[C[CH[now].x]] * W[++tst[C[CH[now].x]]]);
                now--;
    		}
            while (r < A[i].y) {
                r++, vis[seq[r]]++;
                if (vis[seq[r]] == 1) ans += (V[C[seq[r]]] * W[++tst[C[seq[r]]]]);
                else ans -= (V[C[seq[r]]] * W[tst[C[seq[r]]]--]);
            }
            while (l > A[i].x) {
                l--, vis[seq[l]]++;
                if (vis[seq[l]] == 1) ans += (V[C[seq[l]]] * W[++tst[C[seq[l]]]]);
                else ans -= (V[C[seq[l]]] * W[tst[C[seq[l]]]--]);
            }
            while (l < A[i].x) {
                vis[seq[l]]--;
                if (vis[seq[l]] == 1) ans += (V[C[seq[l]]] * W[++tst[C[seq[l]]]]);
                else ans -= (V[C[seq[l]]] * W[tst[C[seq[l]]]--]); 
                l++;
            }
            while (r > A[i].y) {
                vis[seq[r]]--;
                if (vis[seq[r]] == 1) ans += (V[C[seq[r]]] * W[++tst[C[seq[r]]]]);
                else ans -= (V[C[seq[r]]] * W[tst[C[seq[r]]]--]);
                r--;
            }
            if (A[i].flag) {
                vis[A[i].la]++;
                if (vis[A[i].la] == 1) ans += (V[C[A[i].la]] * W[++tst[C[A[i].la]]]);
                else ans -= (V[C[A[i].la]] * W[tst[C[A[i].la]]--]);
            }
            tem[A[i].id] = ans;
            if (A[i].flag) {
                vis[A[i].la]--;
                if (vis[A[i].la] == 1) ans += (V[C[A[i].la]] * W[++tst[C[A[i].la]]]);
                else ans -= (V[C[A[i].la]] * W[tst[C[A[i].la]]--]);	
            }
        }
        for (ll i = 1; i <= tim; i++) printf("%lld
    ", tem[i]);
        return 0;
    }
    
    void add(ll x, ll y) {E[++cnt] = {head[x], y};head[x] = cnt;}
    
    void dfs(ll n, ll ff) {
        in[n] = ++num, fa[0][n] = ff, seq[++len] = n, pos[0][n] = len;
        for (ll i = 1; i <= 20; i++) fa[i][n] = fa[i-1][fa[i-1][n]];
        for (ll i = head[n]; ~i; i = E[i].nt) {
            if (E[i].to == ff) continue; 
            else dep[E[i].to] = dep[n] + 1, dfs(E[i].to, n);
        }
        out[n] = num, seq[++len] = n, pos[1][n] = len;
    }
    
    ll lca(ll x, ll y) {
        if (dep[x] < dep[y]) swap(x, y);
        ll dis = dep[x] - dep[y];
        for (ll i = 20; ~i; i--) if ((dis >> i) & 1) x = fa[i][x];
        if (x == y) return x;
        for (ll i = 20; ~i; i--) if (fa[i][x] != fa[i][y]) x = fa[i][x], y = fa[i][y];
        return fa[0][x];
    }
    
    Yukkuri si te yi te ne
  • 相关阅读:
    android彻底结束进程的两种方法
    清理软件缓存
    android webview 设置
    创建和使用Android library工程
    如何使Android应用程序获得root权限
    自动安装mysql5.7shell脚本实现与ansible脚本实现
    老生常谈:Asp.net Mvc 3 加载cshtml文件创建自定义分页
    老生常谈: Asp.net Mvc3 加载cshtml文件自定义分页+ 查询
    Razor API翻译
    Asp.net MVC 3使用 Area 小结
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13710026.html
Copyright © 2020-2023  润新知