undefined
海阔天空 - Beyond
0:00
  1. 海阔天空Beyond
  2. Weight of the WorldEmi Evansd
  3. 不装饰你的梦蔡国权
  4. 前所未见陈慧琳
  5. 缘份陈松伶
  6. 七夕邓丽欣
  7. 美シキ歌帆足圭吾
  8. 一个人飞李克勤
  9. 好得很麦家瑜
  10. 海觅天秋采桦
  11. 越难越爱吴若希
  12. 形影不离张纹嘉

【GDOI 2016 Day1】疯狂动物城

题目

这里写图片描述

分析

注意注意:码农题一道,打之前做好心理准备。
对于操作1、2,修改或查询xy的路径,显然树链剖分
对于操作2,我们将xy的路径分为xlca(x,y)lca(x,y)y两部分。
对于第一部分的某个点i,设它到y的距离为s,那么s=deep[i]+deep[y]-2*deep[lca(x,y)]i对答案的贡献为a[i]s(s+1)/2,如果不考虑除以2,设t=deep[y]-2*deep[lca(x,y)],则贡献为a[i]*deep[i]2+a[i]*deep[i]*(2*t+1)+a[i]*(t+t2)
对于第二部分的点i,s=deep[y]-deep[i],设lca(x,y),则贡献为a[i]*deep[i]2-a[i]*deep[i]*(2*t+1)+a[i]*(t+t2)
接着,对于每个点i我们就用线段树来维护a[i]*deep[i]^2a[i]*deep[i]以及a[i]
注意:最后记得除2,由于mod 20160501,用逆元。还有,lca(x,y)的贡献会重复,要减掉重复的。
对于操作3,打个可持久化线段树。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=2147483647;
const long long mo=20160501;
using namespace std;
struct trees
{
	long long lazy,l,r;
	long long v1;//a[i]*deep[i]^2
	long long v2;//a[i]*deep[i]
	long long v3;//a[i]
	long long d;
	long long d2;
	
}tree[7000000];
long long g[200005][25],d[200005],son[200005],deep[200005],size[200005],fa[200005],top[200005],bef[200005],f[220005];
long long last[200005],next[200005],to[200005];
long long n,m,ans,t,po,tot,tt;
long long bj(long long x,long long y)
{
	next[++tot]=last[x];
	last[x]=tot;
	to[tot]=y;
}
long long premi()
{
	for(long long j=1;j<=log2(n);j++)
	{
		for(long long i=1;i<=n;i++)
		{
			g[i][j]=g[g[i][j-1]][j-1];
		}
	}
}
long long build(long long x)
{
	size[x]=1;
	g[x][0]=fa[x];
	long long mx=0;
	for(long long i=last[x];i;i=next[i])
	{
		long long j=to[i];
		if(j!=fa[x])
		{
			fa[j]=x;
			deep[j]=deep[x]+1;
			build(j);
			size[x]+=size[j];
			if(size[j]>mx)
			{
				mx=size[j];
				son[x]=j;
			}
		}
	}
}
long long build1(long long x)
{
	d[++tot]=x;
	bef[x]=tot;
	if(!top[x])
	{
		top[x]=x;
	}
	if(son[x])
	{
		top[son[x]]=top[x];
		build1(son[x]);
	}
	for(long long i=last[x];i;i=next[i])
	{
		long long j=to[i];
		if(j!=fa[x] && son[x]!=j)
		{
			build1(j);
		}
	}
}
long long bnew(long long v,long long l,long long r,long long e)
{
	if(l==r)
	{
		tree[v].lazy=0;
		return 0;
	}
	long long mid=(l+r)/2;
	if(e!=2)
	{
		tree[++tot]=tree[tree[v].l];
		if(e==3)
		{
			tree[tot].v1=(tree[tot].v1+tree[v].lazy*tree[tot].d2)%mo;
			tree[tot].v2=(tree[tot].v2+tree[v].lazy*tree[tot].d)%mo;
			tree[tot].v3=(tree[tot].v3+tree[v].lazy*(mid-l+1))%mo;
			tree[tot].lazy=(tree[tot].lazy+tree[v].lazy)%mo;
		}
		tree[v].l=tot;
	}
	if(e>=2)
	{
		tree[++tot]=tree[tree[v].r];
		if(e==3)
		{
			tree[tot].v1=(tree[tot].v1+tree[v].lazy*tree[tot].d2)%mo;
			tree[tot].v2=(tree[tot].v2+tree[v].lazy*tree[tot].d)%mo;
			tree[tot].v3=(tree[tot].v3+tree[v].lazy*(r-(mid+1)+1))%mo;
			tree[tot].lazy=(tree[tot].lazy+tree[v].lazy)%mo;
		}
		tree[v].r=tot;
	}
    tree[v].lazy=0;
}
long long change1(long long v,long long l,long long r,long long x,long long value)
{
	if(l==r)
	{
		tree[v].v3=value;
		tree[v].v2=value*deep[d[l]];
		tree[v].v1=value*deep[d[l]]*deep[d[l]];
		tree[v].d=deep[d[l]];
		tree[v].d2=deep[d[l]]*deep[d[l]];
		return 0;
	}
	long long mid=(l+r)/2;
	if(x<=mid)
	{
		if(!tree[v].l) tree[v].l=++tot;
		change1(tree[v].l,l,mid,x,value);
	}
	else
	{
		if(!tree[v].r) tree[v].r=++tot;
		change1(tree[v].r,mid+1,r,x,value);
	}
	tree[v].v1=tree[tree[v].l].v1+tree[tree[v].r].v1;
	tree[v].v2=tree[tree[v].l].v2+tree[tree[v].r].v2;
	tree[v].v3=tree[tree[v].l].v3+tree[tree[v].r].v3;
	tree[v].d=tree[tree[v].l].d+tree[tree[v].r].d;
	tree[v].d2=tree[tree[v].l].d2+tree[tree[v].r].d2;
}
long long change(long long v,long long l,long long r,long long x,long long y,long long value)
{
	if(l==x && r==y)
	{
		tree[v].v1=tree[v].v1+value*tree[v].d2;
		tree[v].v2=tree[v].v2+value*tree[v].d;
		tree[v].v3=tree[v].v3+value*(r-l+1);
		tree[v].lazy=tree[v].lazy+value;
		return 0;
	}
	bool bz=true;
	if(tree[v].lazy)
	{
		bnew(v,l,r,3);
		bz=false;
	}
	long long mid=(l+r)/2;
	if(y<=mid)
	{
		
		if(bz) bnew(v,l,r,1);
		change(tree[v].l,l,mid,x,y,value);
	}
	else
	if(x>=mid+1)
	{
		if(bz) bnew(v,l,r,2);
		change(tree[v].r,mid+1,r,x,y,value);
	}
	else
	{
		if(bz) bnew(v,l,r,4);
		change(tree[v].l,l,mid,x,mid,value);
		change(tree[v].r,mid+1,r,mid+1,y,value);
	}
	tree[v].v1=tree[tree[v].l].v1+tree[tree[v].r].v1;
	tree[v].v2=tree[tree[v].l].v2+tree[tree[v].r].v2;
	tree[v].v3=tree[tree[v].l].v3+tree[tree[v].r].v3;
}
long long lca(long long x,long long y)
{
	if(deep[x]>deep[y])
	{
		x=x^y;
		y=x^y;
		x=x^y;
	}
	for(long long i=log2(n);i>=0;i--)
	{
		if(deep[g[y][i]]>deep[x])
			y=g[y][i];
	}
	if(deep[y]!=deep[x]) y=g[y][0];
	for(long long i=log2(n);i>=0;i--)
	{
		if(g[y][i]!=g[x][i])
		{
			y=g[y][i];
			x=g[x][i];
		}
	}
	if(x!=y) y=g[y][0];
	return y;
}
long long find(long long v,long long l,long long r,long long x,long long y,long long value,long long o)
{
	if(l==x && r==y)
	{
		return ((tree[v].v1+o*tree[v].v2*(2*value+1)+tree[v].v3*(value+value*value))%mo+mo)%mo;
	}
	if(tree[v].lazy)
	{
		bnew(v,l,r,3);
	}
	long long mid=(l+r)/2,e=0;
	if(y<=mid)
	{
		e=find(tree[v].l,l,mid,x,y,value,o);
	}
	else
	if(x>=mid+1)
	{
		e=find(tree[v].r,mid+1,r,x,y,value,o);
	}
	else
	{
		e=find(tree[v].l,l,mid,x,mid,value,o)+find(tree[v].r,mid+1,r,mid+1,y,value,o);
	}
	tree[v].v1=tree[tree[v].l].v1+tree[tree[v].r].v1;
	tree[v].v2=tree[tree[v].l].v2+tree[tree[v].r].v2;
	tree[v].v3=tree[tree[v].l].v3+tree[tree[v].r].v3;
	return e;
} 
long long work(long long x,long long y,long long z)
{
	if(z)
	{
		f[++t]=++tot;
		tree[tot]=tree[f[tt]];
		tt=t;
		while(top[x]!=top[y])
		{
			if(deep[top[x]]>=deep[top[y]])
			{
				change(f[t],1,n,bef[top[x]],bef[x],z);
				x=fa[top[x]];
			}
			else
			{
				change(f[t],1,n,bef[top[y]],bef[y],z);
				y=fa[top[y]];
			}
		}
		if(deep[x]>=deep[y])
		{
			change(f[t],1,n,bef[y],bef[x],z);
		}
		else
		{
			change(f[t],1,n,bef[x],bef[y],z);
		}
	}
	else
	{
		ans=0;
		long long lc=lca(x,y),xx=x,yy=y;
		long long p=deep[yy]-deep[lc]*2;
		x=xx;
		y=lc;
		if(x!=y)
		{
			while(top[x]!=top[y])
			{
				if(deep[top[x]]>=deep[top[y]])
				{
					ans=((ans+find(f[tt],1,n,bef[top[x]],bef[x],p,1))%mo+mo)%mo;
					x=fa[top[x]];
				}
				else
				{
					ans=((ans+find(f[tt],1,n,bef[top[y]],bef[y],p,1))%mo+mo)%mo;
					y=fa[top[y]];
				}
			}
			if(deep[x]>=deep[y])
			{
				ans=((ans+find(f[tt],1,n,bef[y],bef[x],p,1))%mo+mo)%mo;
			}
			else
			{
				ans=((ans+find(f[tt],1,n,bef[x],bef[y],p,1))%mo+mo)%mo;
			}
			if(lc!=yy) ans=((ans-find(f[tt],1,n,bef[lc],bef[lc],p,1))%mo+mo)%mo;
		}
		x=lc;
		y=yy;
		p=deep[yy];
		if(x!=y)
		{
			while(top[x]!=top[y])
			{
				if(deep[top[x]]>=deep[top[y]])
				{
					ans=((ans+find(f[tt],1,n,bef[top[x]],bef[x],p,-1))%mo+mo)%mo;
					x=fa[top[x]];
				}
				else
				{
					ans=((ans+find(f[tt],1,n,bef[top[y]],bef[y],p,-1))%mo+mo)%mo;
					y=fa[top[y]];
				}
			}
			if(deep[x]>=deep[y])
			{
				ans=((ans+find(f[tt],1,n,bef[y],bef[x],p,-1))%mo+mo)%mo;
			}
			else
			{
				ans=((ans+find(f[tt],1,n,bef[x],bef[y],p,-1))%mo+mo)%mo;
			}
		}
		ans=(ans%mo+mo)*10080251%mo;
		printf("%lld\n",ans);
	}
}
int main()
{
	scanf("%lld%lld",&n,&m);
	for(long long i=1;i<=n-1;i++)
	{
		long long x,y;
		scanf("%lld%lld",&x,&y);
		bj(x,y);
		bj(y,x);
	}
	tot=0;
	deep[1]=1;
	build(1);
	build1(1);
	tot=1;
	f[0]=1;
	t=0;
	tt=0;
 	for(long long i=1;i<=n;i++)
	{
		long long x;
		scanf("%lld",&x);
		change1(1,1,n,bef[i],x);
	}
	premi();
	ans=0;
	for(long long i=1;i<=m;i++)
	{
		long long p,x,y,z;
		scanf("%lld",&p);
		if(p==1)
		{
			scanf("%lld%lld%lld",&x,&y,&z);
			work(x^ans,y^ans,z);
		}
		else
		if(p==2)
		{
			scanf("%lld%lld",&x,&y);
			work(x^ans,y^ans,0);
		}
		else
		{
			scanf("%lld",&x);
			tt=x^ans;
		}
	}
}
posted @ 2018-05-12 19:47  无尽的蓝黄  阅读(296)  评论(0编辑  收藏  举报