zoukankan      html  css  js  c++  java
  • [bzoj3730] 震波

    Description

    在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]。
    不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
    接下来你需要在线处理M次操作:
    0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
    1 x y 表示第x个城市的价值变成了y。
    为了体现程序的在线性,操作中的x、y、k都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为0。

    Input

    第一行包含两个正整数N和M。
    第二行包含N个正整数,第i个数表示value[i]。
    接下来N-1行,每行包含两个正整数u、v,表示u和v之间有一条无向边。
    接下来M行,每行包含三个数,表示M次操作。

    Output

    包含若干行,对于每个询问输出一行一个正整数表示答案。

    Sample Input

    8 1
    1 10 100 1000 10000 100000 1000000 10000000
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    3 8
    0 3 1
    

    Sample Output

    11100101
    

    Solution

    点分树套树状数组。

    先建出点分树,对于每个分治块建一颗树状数组;对于每个分治块的重心,每个儿子的子树也建一颗树状数组。

    树状数组以(dep)为下标,记的是权值之和。

    那么对于修改点权,一共有(O(log n))个分治块和它相交,在树状数组上修改下就好了。

    对于询问也差不多,暴力枚举每个分治块,答案加上树状数组上的值,在减去(x)所在的那颗子树的贡献即可。

    具体的,对于每个点,开个(vector)记录一些四元组,表示分治重心,所在的儿子子树的儿子的编号,到分治重心的距离,以及重心的儿子的树状数组的编号。

    然后大力出奇迹,多(dfs)几遍就做完了。

    注意树状数组需要动态开点,可以对于每个树状数组算出一个最大可以访问到的(dep),然后动态分配内存,这个小(trick)具体可以看代码,树状数组的(build)部分。

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 2e5+10;
    
    int n,m,val[maxn],tot,head[maxn];
    
    struct edge{int to,nxt;}e[maxn<<1];
    
    void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
    void ins(int u,int v) {add(u,v),add(v,u);}
    
    int space[maxn*100],pos,cnt;
    
    struct Binary_Indexed_Tree {
    	int len,*t;
    	void build(int l) {len=l,t=space+pos+2,pos+=l+4;}
    	void modify(int x,int v) {for(int i=x;i<=len;i+=i&-i) t[i]+=v;}
    	int query(int x,int ans=0) {
    		if(x<=0) return 0;x=min(x,len);
    		for(int i=x;i;i-=i&-i) ans+=t[i];return ans;
    	}
    }bit[maxn];
    
    int rt,sz[maxn],f[maxn],vis[maxn],siz,mxdep[maxn],dep[maxn],h[maxn];
    
    struct data {int x,y,dis,bel;};
    
    vector<data > s[maxn];
    
    map<int,int > r[maxn];
    
    void get_rt(int x,int fa) {
    	sz[x]=1,f[x]=0;
    	for(int i=head[x];i;i=e[i].nxt)
    		if(!vis[e[i].to]&&e[i].to!=fa) 
    			get_rt(e[i].to,x),sz[x]+=sz[e[i].to],f[x]=max(f[x],sz[e[i].to]);
    	f[x]=max(f[x],siz-sz[x]);
    	if(f[rt]>f[x]) rt=x;
    }
    
    void get_mxdep(int x,int fa) {
    	dep[x]=dep[fa]+1,mxdep[x]=dep[x];
    	for(int i=head[x];i;i=e[i].nxt)
    		if(e[i].to!=fa&&!vis[e[i].to]) {
    			get_mxdep(e[i].to,x);
    			mxdep[x]=max(mxdep[x],mxdep[e[i].to]);
    		}
    }
    
    int de,de2;
    
    void make(int x,int fa) {
    	bit[cnt].modify(dep[x],val[x]);
    	for(int i=head[x];i;i=e[i].nxt)
    		if(e[i].to!=fa&&!vis[e[i].to]) make(e[i].to,x);
    }
    
    void mark(int x,int fa,int a,int y,int d,int b) {
    	s[x].push_back((data){a,y,d,b});
    	for(int i=head[x];i;i=e[i].nxt)
    		if(!vis[e[i].to]&&e[i].to!=fa) mark(e[i].to,x,a,y,d+1,b);
    }
    
    void build(int x) {
    	get_mxdep(x,0);
    	cnt++;h[x]=cnt;
    	bit[cnt].build(mxdep[x]);
    	de=x;make(x,0);
    	for(int i=head[x];i;i=e[i].nxt)
    		if(!vis[e[i].to]) {
    			dep[x]=0;get_mxdep(e[i].to,x);cnt++;
    			bit[cnt].build(mxdep[e[i].to]+1);
    			de=0;make(e[i].to,x);
    			mark(e[i].to,x,x,e[i].to,1,cnt);
    		}
    	vis[x]=1;
    	for(int i=head[x];i;i=e[i].nxt)
    		if(!vis[e[i].to]) {
    			get_rt(e[i].to,0),siz=sz[e[i].to],rt=0;
    			get_rt(e[i].to,0),build(rt);
    		}
    }
    
    void change(int x,int y) {
    	vector<data > :: iterator it;
    	for(it=s[x].begin();it!=s[x].end();it++) {
    		data da=*it;
    		bit[h[da.x]].modify(da.dis+1,y-val[x]);
    		bit[da.bel].modify(da.dis,y-val[x]);
    	}
    	bit[h[x]].modify(1,y-val[x]);
    	val[x]=y;
    }
    
    int query(int x,int y) {
    	int ans=0;
    	vector<data > :: iterator it;
    	for(it=s[x].begin();it!=s[x].end();it++) {
    		data da=*it;
    		ans+=bit[h[da.x]].query(y-da.dis+1);
    		ans-=bit[da.bel].query(y-da.dis);
    	}
    	ans+=bit[h[x]].query(y+1);
    	return ans;
    }
    
    int main() {
    	read(n),read(m);
    	for(int i=1;i<=n;i++) read(val[i]);
    	for(int i=1,x,y;i<n;i++) read(x),read(y),ins(x,y);
    	siz=n,f[0]=maxn,get_rt(1,0),build(rt);
    	int lstans=0;
    	for(int i=1;i<=m;i++) {
    		int op,x,y;read(op),read(x),read(y);
    		x^=lstans,y^=lstans;
    		if(op==1) change(x,y);
    		else write(lstans=query(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    lhgdialog的传值问题
    jquery中lhgdialog插件(一)
    有关eclipse的内存溢出问题
    oracle数据库cmd导出数据和导入数据
    java replace方法
    jaspersoft中分组打印
    Android开发小技巧之根据position判断ListView是否在显示
    Android开发中Chronometer的用法
    [转][darkbaby]任天堂传——失落的泰坦王朝(下)
    [转][darkbaby]任天堂传——失落的泰坦王朝(中)
  • 原文地址:https://www.cnblogs.com/hbyer/p/10263883.html
Copyright © 2011-2022 走看看