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;
    		}
    	}
    }
    
    
  • 相关阅读:
    C语言I博客作业04
    PTA一般问题汇总与解答
    C语言I博客作业03
    C语言I博客作业02
    C语言I—2019秋作业第一周作业
    C语言I博客作业03
    C语言I博客作业02
    第一周作业
    【2017下集美大学软工1412班_助教博客】团队作业8——测试与发布成绩公示
    《构建之法》读书笔记第8章——需求分析
  • 原文地址:https://www.cnblogs.com/suika/p/10164408.html
Copyright © 2011-2022 走看看