zoukankan      html  css  js  c++  java
  • Bzoj 3730 震波 动态点分治

    Bzoj 3730 震波

    题解:

    和在线的边分治差不多。 就是将每层都信息都存下来。

    然后对于每一层记录上一层的重心是哪个。

    对于求和的话, 从自己的那层出发,然后暴力往上爬, 然后计算答案。

    对于修改来说,也暴力的往上爬,对于每层所对应的信息来修改

    用树状数组来统计同一层、不同深度的前缀和。

    本来想用线段树,然后TLE了,非常卡。

    然后用另一颗树状数组来容斥前缀和。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 5e5;
    int head[N], to[N<<1], nt[N<<1], tot, dtot;
    int in[N], out[N], dfn[N], deep[N];
    int Log[N];
    struct ST {
        int dp[N][20], a[N];
        void init(int n) {
            for(int i = -(Log[0]=-1); i <= n; i++)
                Log[i] = Log[i - 1] + ((i & (i - 1)) == 0);
            for(int i = 1; i <= n; ++i) dp[i][0] = a[i];
            for(int j = 1; j <= Log[n]; j++)
                for(int i = 1; i+(1<<j)-1 <= n; i++){
                    int x = dp[i][j-1], y = dp[i+(1<<(j-1))][j-1];
                    if(deep[x] < deep[y]) dp[i][j] = x;
                    else dp[i][j] = y;
                }
        }
        inline int lca(int l, int r) {
            l = in[l], r = in[r];
            if(l > r) swap(l, r);
            int k = Log[r-l + 1];
            if(deep[dp[l][k]] < deep[dp[r-(1<<k)+1][k]]) return deep[dp[l][k]];
            return dp[r-(1<<k)+1][k];
        }
    }st;
    inline void add(int u, int v){
        to[tot] = v; nt[tot] = head[u]; head[u] = tot++;
    }
    void dfs(int o, int u){
        in[u] = ++dtot;
        st.a[dtot] = u;
        deep[u] = deep[o] + 1;
        for(int i = head[u]; ~i; i = nt[i]){
            int v = to[i];
            if(o ^ v){
                dfs(u, v);
                st.a[++dtot] = u;
            }
        }
    }
    inline int dis(int u, int v){
        return deep[u]+deep[v]-2*deep[st.lca(u, v)];
    }
    int w[N];
    int a[N];
    int atot;
    int Prt[N][2], Pr[N][2];
    vector<int> vc[N][2];
    int vis[N], tsz;
    int sz[N];
    int rt, rtnum;
    int fa[N];
    void Get_root(int o, int u){
        sz[u] = 1;
        int Max = 0;
        for(int i = head[u]; ~i; i = nt[i]){
            int v = to[i];
            if(vis[v] || v == o) continue;
            Get_root(u, v);
            Max = max(Max, sz[v]);
            sz[u] += sz[v];
        }
        Max = max(Max, tsz - sz[u]);
        if(Max < rtnum){
            rt = u;
            rtnum = Max;
        }
    }
    int Maxdep;
    void dfs(int g, int o, int u){
        sz[u] = 1;
        Maxdep = max(Maxdep, dis(g, u));
        for(int i = head[u]; ~i; i = nt[i]){
            int v = to[i];
            if(vis[v] || v == o) continue;
            dfs(g, u, v);
            sz[u] += sz[v];
        }
    }
    void Add(int g, int o, int u){
        a[dis(g, u)] += w[u];
        for(int i = head[u]; ~i ; i = nt[i]){
            int v = to[i];
            if(vis[v] || v == o) continue;
            Add(g, u, v);
        }
    }
    void Run(vector<int> & v){
        for(int i = 0; i <= Maxdep; ++i)
            v.pb(a[i]);
        for(int i = Maxdep; i >= 1; --i){
            int j = i;
            j += i & (-i);
            while(j <= Maxdep){
                v[j] += a[i];
                j += j & (-j);
            }
        }
    }
    void solve(int o, int u, int num){
        tsz = num;
        rtnum = num + 1;
        Get_root(0, u);
        fa[rt] = o;
        vis[rt] = 1;
        Maxdep = 0;
        dfs(rt, 0, rt);/// Find_Max_Deep
        for(int i = 0; i <= Maxdep; ++i)
            a[i] = 0;
        Add(rt, 0, rt);
        Run(vc[rt][0]);
        if(o){
            Maxdep = 0;
            dfs(o, 0, rt);
            for(int i = 0; i <= Maxdep; ++i)
            a[i] = 0;
            Add(o, 0, rt);
            Run(vc[rt][1]);
        }
        int nrt = rt;
        for(int i = head[nrt]; ~i; i = nt[i]){
            int v = to[i];
            if(vis[v]) continue;
            solve(nrt, v, sz[v]);
        }
    }
    void Updata(vector<int> &v, int x, int val){
        int lim = v.size();
        if(x < 0) return ;
        if(x == 0){
            v[0] += val;
            return ;
        }
        while(x < lim){
            v[x] += val;
            x += x & (-x);
        }
    }
    int Query(vector<int> &v, int k){
        int lim = v.size();
        k = min(k, lim-1);
        if(k < 0) return 0;
        int ret = v[0];
        while(k > 0){
            ret += v[k];
            k -= k & (-k);
        }
        return ret;
    }
    void Updata(int x, int val){
        for(int i = x; i; i = fa[i]){
            Updata(vc[i][0], dis(x,i), val);
            if(fa[i]) Updata(vc[i][1], dis(fa[i], x), val);
        }
    }
    int Query(int x, int k){
        int ret = 0;
        for(int i = x; i; i = fa[i]){
            ret += Query(vc[i][0], k-dis(x,i));
            if(fa[i]) ret -= Query(vc[i][1], k-dis(fa[i], x));
        }
        return ret;
    }
    
    struct FastIO {
        static const int S = 1310720;
        int wpos;
        char wbuf[S];
        FastIO() : wpos(0) { }
        inline int xchar() {
            static char buf[S];
            static int len = 0, pos = 0;
            if (pos == len) pos = 0, len = fread(buf, 1, S, stdin);
            if (pos == len) return -1;
            return buf[pos++];
        }
        inline int xint() {
            int c = xchar(), x = 0, s = 1;
            while (c <= 32) c = xchar();
            if (c == '-') s = -1, c = xchar();
            for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
            return x * s;
        }
        ~FastIO() {
            if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
        }
    } io;
    int main(){
        int n, m;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i){
            w[i] = io.xint();
        }
        memset(head, -1, sizeof head);
        for(int i = 1, u, v; i < n; ++i){
            u = io.xint(), v = io.xint();
            add(u, v);  add(v, u);
        }
        dfs(0, 1);
        st.init(dtot);
        solve(0, 1, n);
        int lastans = 0;
        int op, x, y;
        for(int i = 1; i <= m; ++i){
            op = io.xint(), x = io.xint(), y = io.xint();
            x ^= lastans, y ^= lastans;
            if(op){
                Updata(x, y-w[x]);
                w[x] = y;
            }
            else{
                lastans = Query(x,y);
                printf("%d
    ", lastans);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    牛逼哄哄的 RPC 框架,底层到底什么原理?
    你只会用 StringBuilder?试试 StringJoiner,真香!
    厉害了,淘宝千万并发,14 次架构演进…
    微服务中 Zookeeper 应用及原理
    牛逼哄哄的零拷贝是什么?
    排名前 16 的 Java 工具类,哪个你没用过?
    Spring Boot 2.4 正式发布,重大调整!!!
    pl/sql 实例精解 07
    ArcGIS 符号和样式
    SQL Server系统视图有什么用?
  • 原文地址:https://www.cnblogs.com/MingSD/p/11164871.html
Copyright © 2011-2022 走看看