zoukankan      html  css  js  c++  java
  • BZOJ 3626 [LNOI2014]LCA

    题解: dep[LCA(a,b)]等价于把a到根路径+1,然后询问b到根路径的权值

    按左右端点分别排序求出值后作差就可以了

    分块TLE了QWQ

    LCT代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int maxn=50009;
    const int mm=201314;
    
    int n,T;
    
    int fa[maxn],ch[maxn][2],siz[maxn],tag[maxn],sum[maxn],v[maxn];
    inline int son(int x){
    	if(ch[fa[x]][1]==x)return 1;
    	else return 0;
    }
    inline bool isroot(int x){
    	return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x);
    }
    inline void pushup(int x){
    	sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+v[x])%mm;
    	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    }
    inline void pushdown(int x){
    	if(tag[x]){
    		if(ch[x][0]){
    			tag[ch[x][0]]+=tag[x];
    			v[ch[x][0]]+=tag[x];
    			sum[ch[x][0]]=(sum[ch[x][0]]+1LL*siz[ch[x][0]]*tag[x])%mm;
    		}
    		if(ch[x][1]){
    			tag[ch[x][1]]+=tag[x];
    			v[ch[x][1]]+=tag[x];
    			sum[ch[x][1]]=(sum[ch[x][1]]+1LL*siz[ch[x][1]]*tag[x])%mm;
    		}
    		tag[x]=0;
    	}
    }
    void Downfa(int x){
    	if(!isroot(x))Downfa(fa[x]);
    	pushdown(x);
    }
    
    inline void Rotate(int x){
    	int y=fa[x];
    	int z=fa[y];
    	int b=son(x),c=son(y);
    	int a=ch[x][b^1];
    	if(!isroot(y))ch[z][c]=x;
    	fa[x]=z;
    	if(a)fa[a]=y;
    	ch[y][b]=a;
    	fa[y]=x;ch[x][b^1]=y;
    	pushup(y);pushup(x);
    }
    
    void Splay(int x){
    	Downfa(x);
    	while(!isroot(x)){
    		int y=fa[x];
    		if(isroot(y)){
    			Rotate(x);
    		}else{
    			if(son(x)==son(y)){
    				Rotate(y);Rotate(x);
    			}else{
    				Rotate(x);Rotate(x);
    			}
    		}
    	}
    }
    
    void Access(int x){
    	for(int t=0;x;t=x,x=fa[x]){
    		Splay(x);ch[x][1]=t;pushup(x);
    	}
    }
    int Querysum(int x){
    	Access(x);Splay(x);return sum[x];
    }
    void Addpoint(int x){
    	Access(x);Splay(x);
    	tag[x]+=1;v[x]+=1;
    	sum[x]=(sum[x]+siz[x])%mm;
    }
    
    int ql[maxn],qr[maxn],qz[maxn],ans[maxn];
    vector<int>G[maxn];
    int cnt[maxn];
    int main(){
    	scanf("%d%d",&n,&T);
    	for(int i=2;i<=n;++i){
    		int x;
    		scanf("%d",&x);
    		++x;
    		fa[i]=x;
    	}
    	for(int i=1;i<=T;++i){
    		scanf("%d%d%d",&ql[i],&qr[i],&qz[i]);
    		++ql[i];++qr[i];++qz[i];
    	}
    	
    	for(int i=1;i<=n;++i)siz[i]=1;
    	
    	for(int i=1;i<=T;++i){
    		G[ql[i]].push_back(i);
    	}
    	for(int i=1;i<=n;++i){
    		for(int j=0;j<G[i].size();++j){
    			int t=G[i][j];
    			++cnt[t];
    			ans[t]=-Querysum(qz[t]);
    		}
    		Addpoint(i);
    	}
    	
    	memset(tag,0,sizeof(tag));
    	memset(sum,0,sizeof(sum));
    	memset(v,0,sizeof(v));
    	for(int i=1;i<=n;++i)G[i].clear();
    	
    	for(int i=1;i<=T;++i){	
    		G[qr[i]].push_back(i);
    	}
    	for(int i=1;i<=n;++i){
    		Addpoint(i);
    		for(int j=0;j<G[i].size();++j){
    			int t=G[i][j];
    			++cnt[t];
    			ans[t]=(Querysum(qz[t])+ans[t]+mm)%mm;
    		}
    	}
    	
    	for(int i=1;i<=T;++i)printf("%d
    ",ans[i]);
    	return 0;
    }
    

      

    分块代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn=50009;
    const int B=120;
    const int mm=201314;
    
    int n,T;
    int cntedge;
    int head[maxn];
    int to[maxn<<1],nex[maxn<<1];
    void Addedge(int x,int y){
    	nex[++cntedge]=head[x];
    	to[cntedge]=y;
    	head[x]=cntedge;
    }
    
    int dfsclock;
    int father[maxn],dep[maxn],idp[maxn],siz[maxn];
    void Dfs(int now,int fa){
    	father[now]=fa;
    	dep[now]=dep[fa]+1;
    	idp[now]=++dfsclock;
    	siz[now]=1;
    	for(int i=head[now];i;i=nex[i]){
    		if(to[i]==fa)continue;
    		Dfs(to[i],now);
    		siz[now]+=siz[to[i]];
    	}
    }
    
    int f[maxn][maxn/B+1];
    
    int h[maxn];
    void Dp0(int x,int fa){
    	for(int i=head[x];i;i=nex[i]){
    		if(to[i]==fa)continue;
    		Dp0(to[i],x);
    		h[x]+=h[to[i]];
    	}
    }
    void Dp(int x,int fa,int sum,int nowb){
    	f[x][nowb]=sum;
    	
    	for(int i=head[x];i;i=nex[i]){
    		if(to[i]==fa)continue;
    		Dp(to[i],x,(sum+h[to[i]])%mm,nowb);
    	}
    }
    
    int g[maxn][16];
    void LCAinit(){
    	for(int i=1;i<=n;++i)g[i][0]=father[i];
    	for(int j=1;j<=15;++j){
    		for(int i=1;i<=n;++i){
    			g[i][j]=g[g[i][j-1]][j-1];
    		}
    	}
    }
    int Getlca(int u,int v){
    	if(dep[u]<dep[v])swap(u,v);
    	for(int j=15;j>=0;--j){
    		if(dep[g[u][j]]>=dep[v]){
    			u=g[u][j];
    		}
    	}
    	if(u==v)return u;
    	for(int j=15;j>=0;--j){
    		if(g[u][j]!=g[v][j]){
    			u=g[u][j];v=g[v][j];
    		}
    	}
    	return g[u][0];
    }
    
    int main(){
    	scanf("%d%d",&n,&T);
    	for(int i=2;i<=n;++i){
    		int x;
    		scanf("%d",&x);
    		++x;
    		Addedge(x,i);
    	}
    	
    	Dfs(1,0);
    	LCAinit();
    	
    	for(int i=1;i<=n;++i){
    		h[i]=1;
    		if(i%B==0){
    			Dp0(1,0);
    			Dp(1,0,B,i/B);
    			memset(h,0,sizeof(h));
    		}
    	}
    	
    	while(T--){
    		int l,r,x;
    		scanf("%d%d%d",&l,&r,&x);
    		++l;++r;++x;
    		int ans=0;
    		int bl=(l-1)/B+1;
    		int br=(r-1)/B+1;
    		if(bl==br){
    			for(int i=l;i<=r;++i){
    				ans=(ans+dep[Getlca(i,x)])%mm;
    			}
    		}else{
    			for(int i=bl+1;i<=br-1;++i)ans=(ans+f[x][i])%mm;
    			for(int i=l;i<=bl*B;++i)ans=(ans+dep[Getlca(i,x)])%mm;
    			for(int i=(br-1)*B+1;i<=r;++i)ans=(ans+dep[Getlca(i,x)])%mm;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    Java多个版本共存
    在RestHighLevelClient中增加用户名密码验证
    request Body 查询
    threadLocal
    thread 中断 interrupt
    Thread 状态和创建方法
    URI Search
    解析器
    基本crud
    第4章 SQL与关系数据库基本操作
  • 原文地址:https://www.cnblogs.com/zzyer/p/8454353.html
Copyright © 2011-2022 走看看