• Solution -「YunoOI 2007」rfplca


    Description

    Link.

    Given is a rooted tree with the (sf1)-th node as the root.

    The tree will be given in this way: it will tell you that the parent of the (sf i)-th node is (a_{i}).

    Supporting the following operations:

    • 1 l r x: let (sf forall iin[l,r],a_{i}=max{a_{i}-x,1}).
    • 2 u v: find the LCA (Lowest Common Ancestor) of (sf u) and (sf v).

    Solution

    考虑到修改操作是对结点进行的操作,然后这个东西不太能直接 LCT 或树剖,考虑照序列来分块,那么我们来对结点编号分块。

    1. 修改;

    (quad)维护一个属性 (sf top_{u}) 表示在原树上结点 (sf u) 的祖先中不和 (sf u) 在同一个块里面的编号最大的一个结点的编号,如果不存在的话就令 (sf top_{u}=1)。这样的话你从结点 (sf u) 跳到 root 的复杂度为 (sf O(sqrt{n}))。接下来考虑怎么维护这个东西。

    (quad)散块我们直接暴力扫着改;对于整块,可以发现如果一个块的被修改次数超过了块的大小,那么就一定会有 (sf top_{u}=fa_{u})

    1. 询问。

    (quad)分三个类讨论,这个比较好做(差不多和树剖找 LCA 一个样子)。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    LL n,m,top[400010],deln[1000],tag[1000],belong[400010],bl[1000],br[1000],fa[400010],bs;
    #define gtlf(x) ((x-1)*bs+1)
    #define gtrg(x) (min(x*bs,n))
    void updtop(LL x)
    {
    	if(belong[x]^belong[fa[x]])	top[x]=fa[x];
    	else	top[x]=top[fa[x]];
    }
    void turndown(LL x)
    {
    	if(tag[x])
    	{
    		for(LL i=gtlf(x);i<=gtrg(x);++i)	fa[i]=max(fa[i]-tag[x],1ll);
    		tag[x]=0;
    	}
    }
    template<typename T>
    void read(T &hhh)
    {
    	T x=0;
    	char c=getchar();
    	while(c<'0' || c>'9')	c=getchar();
    	while(c>='0' && c<='9')	x=(x<<3)+(x<<1)+(c&15),c=getchar();
    	hhh=x;
    }
    template<typename T>
    void write(T x,char las='
    ')
    {
    	static int st[100],top=0;
    	do st[++top]=x%10,x/=10; while(x);
    	while(top)	putchar(st[top]^'0'),--top;
    	putchar(las);
    }
    int main()
    {
    	read(n),read(m),bs=sqrt(double(n))+1,fa[1]=belong[1]=1;
    	for(LL i=2;i<=n;++i)	read(fa[i]);
    	for(LL i=2;i<=n;++i)	belong[i]=(i-1)/bs+1,updtop(i);
    	LL las=0;
    	while(m--)
    	{
    		LL opt; read(opt);
    		if(opt==1)
    		{
    			LL opl,opr,opx;
    			read(opl),read(opr),read(opx);
    			opl^=las,opr^=las,opx^=las;
    			turndown(belong[opl]);
    			if(belong[opl]==belong[opr])
    			{
    				turndown(belong[opl]);
    				for(LL i=opl;i<=opr;++i)	fa[i]=max(fa[i]-opx,1ll),updtop(i);
    				for(LL i=opr+1;i<=gtrg(belong[opl]);++i)	updtop(i);
    			}
    			else
    			{
    				turndown(belong[opl]);
    				for(LL i=opl;i<=gtrg(belong[opl]);++i)	fa[i]=max(fa[i]-opx,1ll),updtop(i);
    				for(LL i=gtlf(belong[opl]);i<opl;++i)	updtop(i);
    				turndown(belong[opr]);
    				for(LL i=gtlf(belong[opr]);i<=opr;++i)	fa[i]=max(fa[i]-opx,1ll),updtop(i);
    				for(LL i=opr+1;i<=gtrg(belong[opr]);++i)	updtop(i);
    				for(LL i=belong[opl]+1;i<belong[opr];++i)
    				{
    					if(deln[i]>=bs)	tag[i]+=opx;
    					else
    					{
    						++deln[i];
    						for(LL j=gtlf(i);j<=gtrg(i);++j)	fa[j]=max(fa[j]-opx,1ll),updtop(j);
    					}
    				}
    			}
    		}
    		else
    		{
    			LL opx,opy; read(opx),read(opy);
    			opx^=las,opy^=las;
    			while(opx^opy)
    			{
    				LL fopx,fopy;
    				if(deln[belong[opx]] < bs) fopx=top[opx];
    				else fopx = max(1LL , fa[opx] - tag[belong[opx]]);
    				if(deln[belong[opy]] < bs) fopy=top[opy];
    				else fopy = max(1LL , fa[opy] - tag[belong[opy]]);
    				if(belong[opx]^belong[opy])
    				{
    					if(belong[opx]>belong[opy])	opx=fopx;
    					else	opy=fopy;
    				}
    				else if(fopx^fopy)	opx=fopx,opy=fopy;
    				else
    				{
    					if(opx>opy)	turndown(belong[opx]),opx=max(1LL , fa[opx] - tag[belong[opx]]);
    					else	turndown(belong[opy]),opy=max(1LL , fa[opy] - tag[belong[opy]]);
    				}
    			}
    			write(las=opx);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    开启Spring Boot 之旅
    Java笔试面试练习题---集合
    Python
    Python
    Redis -下载与基本使用
    Git
    Vue全家桶-Vue-router&Vuex
    Es6
    Vue-前端
    Django基础及实战
  • 原文地址:https://www.cnblogs.com/orchid-any/p/14613118.html
Copyright © 2020-2023  润新知