[Ynoi2007]rfplca
rfplca
题解
看到这种恶心的序列区间操作应该很容易想到通过分块来进行维护。好像也不能用什么线段树之类的
 我们考虑对于同一个块里每个点最远能跳到该块内的那个点,再跳就跳出去了。
 很显然,我们每对一个块进行一次修改就会让该块内的更多的点再跳一次就跳出去,毕竟 
     
      
       
        
        
          a 
         
        
          i 
         
        
       
      
        a_{i} 
       
      
    ai是不断减少的。
 而一个点如果想要跳出该块,显然我们对其进行进行的操作是不会超过 
     
      
       
       
         S 
        
       
      
        S 
       
      
    S即块长次的。
 所以我们对一个块的整体修改操作次数是不会超过 
     
      
       
       
         S 
        
       
      
        S 
       
      
    S的,之后的话就暴力记录下来该块被整体操作了多少次,在跳的时候对其的 
     
      
       
        
        
          a 
         
        
          i 
         
        
       
      
        a_{i} 
       
      
    ai减去 
     
      
       
       
         l 
        
       
         z 
        
        
        
          y 
         
         
         
           b 
          
         
           l 
          
         
           o 
          
         
           c 
          
          
          
            k 
           
          
            i 
           
          
         
        
       
      
        lzy_{block_{i}} 
       
      
    lzyblocki即可。
 我们每次查询的话就可以一个块一个块的跳,直到找到它们的 
     
      
       
       
         l 
        
       
         c 
        
       
         a 
        
       
      
        lca 
       
      
    lca为止,毕竟我们是处理出每个点在块内最远跳到那里的。
时间复杂度显然是 O ( n S + n m S ) ⩾ O ( n 2 m 3 ) ≈ O ( ( n + m ) n ) O\left(nS+\frac{nm}{S}\right)\geqslant O\left(\sqrt[3]{n^2m}\right)\approx O\left((n+m)\sqrt{n}\right) O(nS+Snm)⩾O(3n2m)≈O((n+m)n)。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 400010
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;     
const LL INF=0x3f3f3f3f3f3f3f3f;  
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int n1=300;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){putchar('\n');while(x>9){putchar((x%10)|'0');x/=10;}putchar(x|'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
const int M=MAXN/n1+5;
int n,q,a[MAXN],block[MAXN],L[M],R[M],nxt[MAXN],lzy[M],lans;
void TagBlock(int x){for(int i=L[x];i<=R[x];i++)a[i]=max(a[i]-lzy[x],1);lzy[x]=0;}
void SetBlock(int x){for(int i=L[x];i<=R[x];i++)if(a[i]<L[x])nxt[i]=i;else nxt[i]=nxt[a[i]];}
signed main(){
	read(n);read(q);for(int i=2;i<=n;i++)read(a[i]);
	for(int i=1;i<=n;i++)block[i]=(i+n1-1)/n1;
	for(int i=1;i<=n;i++){if(!L[block[i]])L[block[i]]=i;R[block[i]]=i;}
	for(int i=1;i<=block[n];i++)SetBlock(i);
	for(int i=1;i<=q;i++){
		int opt;read(opt);
		if(opt==1){
			int l,r,x;read(l);read(r);read(x);l^=lans;r^=lans;x^=lans;
			if(block[l]==block[r]){
				TagBlock(block[l]);
				for(int j=l;j<=r;j++)a[j]=max(a[j]-x,1);
				SetBlock(block[l]);
			}
			else{
				TagBlock(block[l]);for(int j=l;j<=R[block[l]];j++)a[j]=max(a[j]-x,1);SetBlock(block[l]);
				TagBlock(block[r]);for(int j=L[block[r]];j<=r;j++)a[j]=max(a[j]-x,1);SetBlock(block[r]);
				for(int j=block[l]+1;j<block[r];j++)lzy[j]=min(lzy[j]+x,n);
			}
		}
		else{
			int u,v;read(u);read(v);u^=lans;v^=lans;
			while(u^v){
				if(block[u]<block[v])swap(u,v);
				if(block[u]^block[v]){
					if((nxt[u]^u)&&lzy[block[u]])
						TagBlock(block[u]),SetBlock(block[u]);
					u=max(a[nxt[u]]-lzy[block[u]],1);
				}
				else{
					if(((nxt[u]^u)||(nxt[v]^v))&&lzy[block[u]])
						TagBlock(block[u]),SetBlock(block[u]);
					if(nxt[u]^nxt[v])u=max(a[nxt[u]]-lzy[block[u]],1),v=max(a[nxt[v]]-lzy[block[v]],1);
					else while(u^v){if(u<v)swap(u,v);u=a[u];}
				}
			}
			printf("%d\n",lans=u);
		}
	}
	return 0;
}
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号