• 雅礼集训


    [雅礼集训Day1]

    真•神仙打架,考出来9分,暴力打炸?!总结一下第一题。
    一道经典的支持换根的树链剖分,需要支持的操作有:
    1.将根设为root.
    2.设u, v的最近公共祖先为p, 将p的子树中的所有点的权值加上x.
    3.查询u的子树中的所有点的权值和.
    对于这一类题目,其实我们并不需要真正去换根,我们只需要记录一下当前的根是谁,然后在更改和查询的时候修改一下即可。
    这道题真正的难点在于如何确定lca
    题解:
    经过一些简单的讨论可以知道,(u)(v)在以(root)为根时的(lca)为:(lca(u, v)),(lca(u, root)),(lca(v, root))中原来深度最大的一个,其中(lca(a, b))代表(a),(b)在以(1)为根时的(lca)
    太菜了并不会证,所以记一下结论吧
    确定了(lca)之后就好做了,对于查询操作,判断当前(root)是否在(u)的子树中,
    如果不在,直接查询原来的子树
    如果在,运用dfs序的连续性排除(root)所在儿子的子树,查询其他即可。画图模拟一下很好看出来。
    注意特判(u)是否是(root)因为这个调了好久

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<queue>
    #define debug cout<<"....."<<endl;
    #define lll long long
    #define ll(x) (x*2)
    #define rr(x) (x*2+1)
    using namespace std;
    lll read()
    {
    	lll x=0,w=1;char ch=getchar();
    	while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return x*w;
    }
    lll n,q,cnt,m,opt,x,y,z,node;
    lll head[300010],deep[300010],a[300010],size[300010],s[300010],pos[3000010];
    lll sgm[1200010],lazy[1200010];
    lll f[300010][21];
    struct node{
    	lll to,next;
    }edge[600010];
    void add(lll x,lll y)
    {
    	cnt++;edge[cnt].to=y;edge[cnt].next=head[x];head[x]=cnt;
    }
    void init()
    {
    	for(lll i=1;i<=20;i++)
    		for(lll j=1;j<=n;j++)
    			f[j][i]=f[f[j][i-1]][i-1];
    }
    void dfs(lll k,lll fa)
    {
    	lll v;
    	s[++m]=k;pos[k]=m;
    	for(lll i=head[k];i;i=edge[i].next)
    	{
    		v=edge[i].to;
    		if(v==fa) continue;
    		deep[v]=deep[k]+1;f[v][0]=k;
    		dfs(v,k);
    		size[k]+=size[v];
    	}
    	size[k]++;
    }
    lll LCA(lll x,lll y)
    {
    	if(deep[x]<deep[y]) swap(x,y);
    	for(lll i=20;i>=0;i--)
    		if(deep[f[x][i]]>=deep[y]) x=f[x][i];
    	if(x==y) return x;
    	for(lll i=20;i>=0;i--)
    		if(f[x][i]!=f[y][i])
    			x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    void push_down(lll root,lll l,lll r)
    {
    	lll mid=(l+r)/2;
    	if(!lazy[root]) return;
    	sgm[ll(root)]+=(mid-l+1)*lazy[root];sgm[rr(root)]+=(r-mid)*lazy[root];
    	lazy[ll(root)]+=lazy[root];lazy[rr(root)]+=lazy[root];lazy[root]=0;
    	return;
    }
    void build(lll root,lll l,lll r)
    {
    	if(l>r) return;
    	if(l==r)
    	{
    		sgm[root]=a[s[l]];
    		return;
    	}
    	lll mid=(l+r)/2;
    	if(l<=mid) build(ll(root),l,mid);
    	if(r>mid) build(rr(root),mid+1,r);
    	sgm[root]=sgm[ll(root)]+sgm[rr(root)];
    }
    void insert(lll root,lll l,lll r,lll left,lll right,lll v)
    {
    	if(l>r) return;
    	if(l>right||r<left) return;
    	if(left<=l&&r<=right)
    	{
    		sgm[root]+=(r-l+1)*v;lazy[root]+=v;
    		return;
    	}
    	lll mid=(l+r)/2;
    	push_down(root,l,r);
    	if(l<=mid) insert(ll(root),l,mid,left,right,v);
    	if(r>mid) insert(rr(root),mid+1,r,left,right,v);
    	sgm[root]=sgm[ll(root)]+sgm[rr(root)];
    }
    lll query(lll root,lll l,lll r,lll left,lll right)
    {
    	if(l>r) return 0;
    	if(l>right||r<left) return 0;
    	if(left<=l&&r<=right) return sgm[root];
    	lll mid=(l+r)/2;
    	push_down(root,l,r);
    	return query(ll(root),l,mid,left,right)+query(rr(root),mid+1,r,left,right);
    }
    int main()
    {
    	freopen("tree.in","r",stdin);
    	freopen("tree.out","w",stdout);
    	n=read();q=read();node=1;
    	for(lll i=1;i<=n;i++) a[i]=read();
    	for(lll i=1;i<n;i++)
    	{
    		x=read();y=read();
    		add(x,y);add(y,x);
    	}
    	deep[1]=1;
    	dfs(1,0);
    	build(1,1,n);
    	init();
    	for(lll i=1;i<=q;i++)
    	{
    		opt=read();
    		if(opt==1)
    			node=read();
    		else if(opt==2)
    		{
    			x=read();y=read();z=read();
    			lll lca,lca1=LCA(x,y),lca2=LCA(x,node),lca3=LCA(y,node);
    			if(deep[lca1]>=deep[lca2]&&deep[lca1]>=deep[lca3]) lca=lca1;
    			else if(deep[lca2]>=deep[lca1]&&deep[lca2]>=deep[lca3]) lca=lca2;
    			else if(deep[lca3]>=deep[lca2]&&deep[lca3]>=deep[lca1]) lca=lca3;
    			lll l=LCA(lca,node);
    			if(lca==node) insert(1,1,n,1,n,z);
    			else if(l==lca&&lca!=node)
    			{
    				l=node;
    				for(lll i=20;i>=0;i--)
    					if(deep[f[l][i]]>deep[lca]) l=f[l][i];
    				insert(1,1,n,1,n,z);insert(1,1,n,pos[l],pos[l]+size[l]-1,-z);
    			}
    			else insert(1,1,n,pos[lca],pos[lca]+size[lca]-1,z);
    		}
    		else if(opt==3)
    		{
    			x=read();
    			lll l=LCA(x,node);
    			if(x==node) printf("%lld
    ",query(1,1,n,1,n));
    			else if(l==x&&x!=node)
    			{
    				l=node;
    				for(lll i=20;i>=0;i--)
    					if(deep[f[l][i]]>deep[x]) l=f[l][i];
    				printf("%lld
    ",query(1,1,n,1,pos[l]-1)+query(1,1,n,pos[l]+size[l],n));
    			}
    			else printf("%lld
    ",query(1,1,n,pos[x],pos[x]+size[x]-1));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    The requested resource (/) is not available解决办法
    字符问题
    Unknown column in 'field list'
    table 和 div 简单布局
    css简介
    div 与 table 的优点
    瞎搞
    html
    小计--关联 复制表结构
    ddl dml dcl
  • 原文地址:https://www.cnblogs.com/lsgjcya/p/9218709.html
Copyright © 2020-2023  润新知