zoukankan      html  css  js  c++  java
  • 【BZOJ】3730: 震波

    原题链接

    题解

    查询距离一个点距离在一定范围内的点,直接点分树,前缀和用树状数组维护
    答案是当前重心距离不超过k - (x到重心距离)的点的前缀和,减去在x所在子树中,距离重心不超过k - (x到重心距离)的前缀和

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 +c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int lowbit(int x) {
        return x & (-x);
    }
    struct BIT {
        vector<int64> v;
        void init(int n) {
    	for(int i = 1 ; i <= n + 1 ; ++i) v.pb(0);
        }
        void Insert(int x,int64 p) {
    	while(x < v.size()) {
    	    v[x] += p;
    	    x += lowbit(x);
    	}
        }
        int64 Query(int x) {
    	int64 res = 0;
    	x = min(x,(int)v.size() - 1);
    	while(x > 0) {
    	    res += v[x];
    	    x -= lowbit(x);
    	}
    	return res;
        }
    };
    struct node {
        int to,next;
    }E[MAXN * 2];
    struct pdt {
        BIT rt,pre;
        vector<int> aux,sub,dep;
    }tr[MAXN];
    int head[MAXN],sumE;
    int N,M,d[MAXN];
    int64 val[MAXN];
    bool vis[MAXN];
    vector<int> poi;
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    int Calc_G(int st) {
        static int fa[MAXN],siz[MAXN],son[MAXN],que[MAXN],ql,qr;
        ql = 1,qr = 0;
        que[++qr] = st;
        fa[st] = 0;siz[st] = 1;son[st] = 0;
        while(ql <= qr) {
    	int u = que[ql++];
    	for(int i = head[u] ; i ; i = E[i].next) {
    	    int v = E[i].to;
    	    if(v != fa[u] && !vis[v]) {
    		fa[v] = u;siz[v] = 1;son[v] = 0;que[++qr] = v;
    	    }
    	}
        }
        int res = que[qr];
        for(int i = qr ; i >= 1 ; --i) {
    	int u = que[i];
    	if(fa[u]) {
    	    siz[fa[u]] += siz[u];
    	    son[fa[u]] = max(son[fa[u]],siz[u]);
    	}
    	son[u] = max(son[u],qr - siz[u]);
    	if(son[u] < son[res]) res = u;
        }
        return res;
    }
    int get_max_dep(int u,int fa) {
        d[u] = d[fa] + 1;
        int res = d[u];
        poi.pb(u);
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(!vis[v] && v != fa) {
    	    res = max(res,get_max_dep(v,u));
    	}
        }
        return res;
    }
    void dfs_divide(int u) {
        int G = Calc_G(u);
        vis[G] = 1;
        d[G] = 1;
        poi.clear();
        tr[G].rt.init(get_max_dep(G,0));
        for(int i = 0 ; i < poi.size() ; ++i) {
    	tr[G].rt.Insert(d[poi[i]],val[poi[i]]);
    	tr[poi[i]].aux.pb(G);
    	tr[poi[i]].dep.pb(d[poi[i]]);
        }
        for(int i = head[G] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(!vis[v]) {
    	    int s = Calc_G(v);
    	    poi.clear();
    	    tr[s].pre.init(get_max_dep(v,G));
    	    for(int j = 0 ; j < poi.size() ; ++j) {
    		tr[poi[j]].sub.pb(s);
    		tr[s].pre.Insert(d[poi[j]],val[poi[j]]);
    	    }
    	}
        }
        for(int i = head[G] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(!vis[v]) dfs_divide(v);
        }
    }
    void Init() {
        read(N);read(M);
        int u,v;
        for(int i = 1 ; i <= N ; ++i) read(val[i]);
        for(int i = 1 ; i < N ; ++i) {
    	read(u);read(v);
    	add(u,v);add(v,u);
        }
        dfs_divide(1);
    }
    int64 Calc(int x,int k) {
        int64 res = 0;
        for(int i = tr[x].aux.size() - 1 ; i >= 0 ; --i) {
    	int u = tr[x].aux[i];
    	res += tr[u].rt.Query(k + 2 - tr[x].dep[i]);
        }
        for(int i = tr[x].sub.size() - 1 ; i >= 0 ; --i) {
    	int u = tr[x].sub[i];
    	res -= tr[u].pre.Query(k + 2 - tr[x].dep[i]);
        }
        return res;
    }
    void Change(int x,int y) {
        for(int i = tr[x].aux.size() - 1 ; i >= 0 ; --i) {
    	int u = tr[x].aux[i];
    	tr[u].rt.Insert(tr[x].dep[i],-val[x]);
    	tr[u].rt.Insert(tr[x].dep[i],y);
        }
        for(int i = tr[x].sub.size() - 1 ; i >= 0 ; --i) {
    	int u = tr[x].sub[i];
    	tr[u].pre.Insert(tr[x].dep[i],-val[x]);
    	tr[u].pre.Insert(tr[x].dep[i],y);
        }
        val[x] = y;
    }
    void Solve() {
        int la = 0;
        int x,op,y;
        for(int i = 1 ; i <= M ; ++i) {
    	read(op);read(x);read(y);
    	x = x ^ la;y = y ^ la;
    	if(op == 0) {
    	    la = Calc(x,y);
    	    out(la);enter;
    	}
    	else {
    	    Change(x,y);
    	}
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
    }
    
  • 相关阅读:
    jsp 生成验证码代码
    成为Java顶尖程序员 ,看这11本书就够了
    自动清除浏览器缓存-Cache Killer
    移动端-ios-上拉加载卡顿
    移动端-ios-点击阴影去除
    转--Android开发实践:使用Service还是Thread
    Android入门:Handler简介与实例
    Spring事务的隔离级别
    ThreadLocal的内存泄漏问题
    Spring 使用注解方式进行事务
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10641733.html
Copyright © 2011-2022 走看看