• BZOJ3052: [wc2013]糖果公园【树上带修莫队】


    Description

    img

    Input

    img

    Output

    img

    Sample Input

    img

    Sample Input

    Sample Output

    84
    131
    27
    84

    HINT

    img

    img


    思路

    非常模板的树上带修莫队

    真的很裸

    直接暴力维护就可以了

    注意一下询问的第二关键字是第二个节点所在块,第三关键字是时间,不然jmr说会出锅


    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 1e5 + 10;
    
    int n, m, q, col[N], c[N];
    int dfn[N], dfn_ind = 0;
    int dep[N], fa[N][20];
    int tot = 0, head[N];
    ll v[N], w[N], nowans = 0;
    int top = 0, st[N << 1], bel[N];
    int siz_block = 2000, cnt_block = 0;
    int num[N], vis[N];
    
    struct Query {
      int u, v, id;
      ll ans;
    } Q[N];
    
    bool cmp1(const Query &a, const Query &b) {
      if (bel[a.u] != bel[b.u]) return bel[a.u] < bel[b.u];
      if (bel[a.v] != bel[b.v]) return bel[a.v] < bel[b.v];
      return a.id < b.id;
    }
    
    bool cmp2(const Query &a, const Query &b) {
      return a.id < b.id;
    }
    
    struct Modify {
      int pos, bef, aft, id;
    } M[N << 1];
    
    struct Edge {
      int v, nxt;
    } E[N << 1];
    
    
    void addedge(int u, int v) {
      E[++tot] = (Edge) {v, head[u]};
      head[u] = tot;
    } 
    
    int dfs(int u) {
      int siz = 0;
      dfn[u] = ++dfn_ind;
      for (int i = 1; i <= 18; i++)
        fa[u][i] = fa[fa[u][i - 1]][i - 1];
      for (int i = head[u]; i; i = E[i].nxt) {
        int v = E[i].v;
        if (v == fa[u][0]) continue;
        fa[v][0] = u;
        dep[v] = dep[u] + 1;
        siz += dfs(v);
        if (siz >= siz_block) {
          ++cnt_block;
          while (siz) {
            bel[st[top--]] = cnt_block;
            --siz;
          }
        }
      }
      st[++top] = u;
      return siz + 1;
    }
    
    int lca(int x, int y) {
      if (dep[x] < dep[y]) swap(x, y);
      int delta = dep[x] - dep[y];
      for (int i = 0; i <= 18; i++)
        if ((delta >> i) & 1) x = fa[x][i];
      if (x == y) return x;
      for (int i = 18; i >= 0; i--) {
        if (fa[x][i] != fa[y][i]) {
          x = fa[x][i];
          y = fa[y][i];
        }
      }
      return fa[x][0];
    }
    
    void reverse(int x) {
      if (vis[x]) {
        nowans -= w[num[col[x]]] * v[col[x]];
        num[col[x]]--;  
      } else {
        num[col[x]]++;
        nowans += w[num[col[x]]] * v[col[x]];
      }
      vis[x] ^= 1;
    }
    
    void solve(int x, int y) {
      while (x != y) {
        if (dep[x] > dep[y]) {
          reverse(x);
          x = fa[x][0];
        } else {
          reverse(y);
          y = fa[y][0];
        }
      }
    }
    
    int main() {
    #ifdef dream_maker
      freopen("input.txt", "r", stdin);
    #endif
      scanf("%d %d %d", &n, &m, &q);
      for (int i = 1; i <= m; i++) scanf("%lld", &v[i]);
      for (int i = 1; i <= n; i++) scanf("%lld", &w[i]);
      for (int i = 1; i < n; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        addedge(u, v);
        addedge(v, u);
      }
      for (int i = 1; i <= n; i++) {
        scanf("%d", &col[i]);
        c[i] = col[i];
      }
      int cntq = 0, cntm = 0;
      for (int i = 1; i <= q; i++) {
        int typ; scanf("%d", &typ);
        if (typ) {
          ++cntq;
          Q[cntq].id = i;
          scanf("%d %d", &Q[cntq].u, &Q[cntq].v);
        } else {
          ++cntm;
          M[cntm].id = i;
          int x, y;
          scanf("%d %d", &x, &y);
          M[cntm].pos = x;
          M[cntm].bef = c[x];
          c[x] = y;
          M[cntm].aft = c[x];
        }
      }
      dfs(1);
      ++cnt_block;
      while (top) {
        bel[st[top--]] = cnt_block;
      }
      sort(Q + 1, Q + cntq + 1, cmp1);
      int cur = 0;
      for (int i = 1; i <= cntq; i++) {
        while (cur < cntm && M[cur + 1].id <= Q[i].id) {
          ++cur;
          if (vis[M[cur].pos]) {
            nowans -= w[num[col[M[cur].pos]]] * v[col[M[cur].pos]];
            num[col[M[cur].pos]]--;
          }
          col[M[cur].pos] = M[cur].aft;
          if (vis[M[cur].pos]) {
            num[col[M[cur].pos]]++;
            nowans += w[num[col[M[cur].pos]]] * v[col[M[cur].pos]];
          } 
        }
        while (cur >= 1 && M[cur].id >= Q[i].id) {
          if (vis[M[cur].pos]) {
            nowans -= w[num[col[M[cur].pos]]] * v[col[M[cur].pos]];
            num[col[M[cur].pos]]--;
          }
          col[M[cur].pos] = M[cur].bef;
          if (vis[M[cur].pos]) {
            num[col[M[cur].pos]]++;
            nowans += w[num[col[M[cur].pos]]] * v[col[M[cur].pos]];
          } 
          --cur;
        }
        if (i == 1) {
          solve(Q[i].u, Q[i].v);
        } else {
          solve(Q[i].u, Q[i - 1].u);
          solve(Q[i].v, Q[i - 1].v);
        }
        int t = lca(Q[i].u, Q[i].v);
        reverse(t);
        Q[i].ans = nowans;
        reverse(t);
      }
      sort(Q + 1, Q + cntq + 1, cmp2);
      for (int i = 1; i <= cntq; i++) 
        printf("%lld
    ", Q[i].ans);
      return 0;
    }
    
  • 相关阅读:
    IDEA远程仓库版本回滚
    智能风控平台核心之风控决策引擎(三)
    智能风控平台核心之风控决策引擎(一)
    深入理解Oracle的imp/exp 和各版本之间的规则
    oracle忘记用户密码
    Windows下使用cmd启动Oracle EM和sql命令使用+主机身份认证
    jsp调用javabean出现错误HTTP Status 500
    jsp查询页面和结果页面在同一页面显示和交互
    javabean+servlet+jsp程序_个人辛苦探索
    用Eclipse 开发Dynamic Web Project应用程序 【转】
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/10195773.html
Copyright © 2020-2023  润新知