• 【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
    ",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;
    		}
    	}
    }
    
  • 相关阅读:
    thinkpad的trackpoint在webstorm或phpstorm下滚动条失效的解决方案
    SQL 中操作XML类型数据
    远程调试项目
    2021031520210321 助教一周小结(第七周)
    2021030820210314 助教一周小结(第六周)
    2021030120210307 助教一周小结(第五周)
    2021022220210228 助教一周小结(第四周)
    2021020820210214 助教一周小结(第二周)
    2021021520210221 助教一周小结(第三周)
    2021032220210328 助教一周小结(第八周)
  • 原文地址:https://www.cnblogs.com/chen1352/p/9029674.html
Copyright © 2020-2023  润新知