zoukankan      html  css  js  c++  java
  • BZOJ3730: 震波

    BZOJ3730: 震波

    https://lydsy.com/JudgeOnline/problem.php?id=3730

    分析:

    • 对于点分树上的每个点(x),维护子树所有点到(x)的距离和到点分树上(fa[x])的距离 。
    • 查询时查询(x)在点分树上到根的一条链,容斥计算答案。
    • 然后因为有修改我们使用树状数组。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <vector>
    #include <iostream>
    using namespace std;
    #define N 100050
    char buf[100000],*p1,*p2;
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int rd() {
    	int x=0;
    	char s=nc();
    	while(s<'0') s=nc();
    	while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
    	return x;
    }
    #define db(x) cerr<<#x<<" = "<<x<<endl
    int head[N],to[N<<1],nxt[N<<1],cnt,n,m,val[N];
    int siz[N],fk[N],root,tot,used[N],fa[N][20],dis[N][20],dep[N];
    struct Bit {
    	vector<int>b;
    	void make(int s) {b.resize(s+2);}
    	void fix(int x,int v) {
    		x++;
    		int lim=b.size();
    		for(;x<lim;x+=x&(-x)) b[x]+=v;
    	}
    	int inq(int x) {
    		x++;
    		int re=0;
    		x=min(x,int(b.size())-1);
    		for(;x;x-=x&(-x)) re+=b[x];
    		return re;
    	}
    }f1[N],f2[N];
    inline void add(int u,int v) {
    	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
    }
    void gr(int x,int y) {
    	int i;
    	siz[x]=1; fk[x]=0;
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
    		gr(to[i],x); siz[x]+=siz[to[i]];
    		fk[x]=max(fk[x],siz[to[i]]);
    	}
    	fk[x]=max(fk[x],tot-siz[x]);
    	if(fk[root]>fk[x]) root=x;
    }
    int mxd;
    void gd(int x,int y,int rt,int d) {
    	int i;
    	mxd=max(mxd,d);
    	for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
    		mxd=max(mxd,dis[to[i]][dep[to[i]]]);
    		fa[to[i]][++dep[to[i]]]=rt;
    		dis[to[i]][dep[to[i]]]=d;
    		gd(to[i],x,rt,d+1);
    	}
    }
    void solve(int x) {
    	used[x]=1;
    	int i;
    	mxd=0;
    	gd(x,0,x,1);
    	f1[x].make(mxd); f2[x].make(mxd);
    	int all=tot;
    	for(i=head[x];i;i=nxt[i]) if(!used[to[i]]) {
    		tot=siz[to[i]]; 
    		root=0; gr(to[i],x); solve(root);
    	}
    }
    void upd(int x,int v) {
    	int i;
    	f1[x].fix(0,v);
    	f2[x].fix(dis[x][dep[x]],v);
    	for(i=dep[x];i;i--) {
    		f1[fa[x][i]].fix(dis[x][i],v);
    		f2[fa[x][i]].fix(dis[x][i-1],v);
    	}
    }
    int query(int x,int k) {
    	int i,re=f1[x].inq(k);
    	for(i=dep[x];i;i--) {
    		if(k>=dis[x][i]) {
    			re+=f1[fa[x][i]].inq(k-dis[x][i]);
    			re-=f2[fa[x][i+1]].inq(k-dis[x][i]);
    		}
    	}
    	return re;
    }
    int main() {
    	n=rd(),m=rd();
    	int i,x,y,opt;
    	for(i=1;i<=n;i++) val[i]=rd();
    	for(i=1;i<n;i++) {
    		x=rd(), y=rd();
    		add(x,y); add(y,x);
    	}
    	tot=n;
    	fk[0]=1ll<<30;
    	gr(1,0);
    	solve(root);
    	for(i=1;i<=n;i++) fa[i][dep[i]+1]=i;
    	for(i=1;i<=n;i++) upd(i,val[i]);
    	int ans=0;
    	while(m--) {
    		opt=rd(), x=rd(), y=rd();
    		x^=ans, y^=ans;
    		if(!opt) {
    			ans=query(x,y);
    			printf("%d
    ",ans);
    		}else {
    			upd(x,y-val[x]), val[x]=y;
    		}
    	}
    }
    
    
  • 相关阅读:
    December 23rd 2016 Week 52nd Friday
    December 22nd 2016 Week 52nd Thursday
    December 21st 2016 Week 52nd Wednesday
    December 20th 2016 Week 52nd Tuesday
    December 19th 2016 Week 52nd Sunday
    December 18th 2016 Week 52nd Sunday
    uva294(唯一分解定理)
    uva11624Fire!(bfs)
    fzu2150Fire Game(双起点bfs)
    poj3276Face The Right Way
  • 原文地址:https://www.cnblogs.com/suika/p/10164408.html
Copyright © 2011-2022 走看看