zoukankan      html  css  js  c++  java
  • CF226E Noble Knight's Path

    XIII.CF226E Noble Knight's Path

    这题分为在线和离线两种做法然而我只会在线

    在线的思路很简单,即先树剖,然后建出主席树。主席树一维维护的是时间,每一棵主席树内部维护的是树剖剖出来的结果。

    然后对于每一次询问:

    首先先从两边跳链,找到LCA,并找出两点路径间没有被“亵渎”的城堡数。如果这一数量小于询问,直接输出\(-1\)

    否则,先从\(x\)往上一直跳到LCA,如果这一段中未被“亵渎”的城堡数已经足够了,就直接输出;否则,从\(y\)点向上跳,类似地找未被亵渎的城堡。

    那怎么输出呢?这就要在线段树上二分了。当然,反正总复杂度已经是\(\log^2\)了,你要嫌麻烦直接写\(\log^2\)的二分套线段树也没有问题,毕竟线段树上二分写起来确实挺恶心的。不过这里写的还是线段树上二分。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100100;
    int n,m,des[N];
    //------------------------Chain Decompotision---------------
    int dfn[N],rev[N],fa[N],dep[N],son[N],top[N],sz[N],head[N],cnt,tot;
    struct node{
    	int to,next;
    }edge[200100];
    void ae(int u,int v){
    	edge[cnt].next=head[u],edge[cnt].to=v,head[u]=cnt++;
    	edge[cnt].next=head[v],edge[cnt].to=u,head[v]=cnt++;
    }
    void dfs1(int x,int Fa){
    	fa[x]=Fa,dep[x]=dep[Fa]+1,sz[x]=1;
    	for(int i=head[x],y;i!=-1;i=edge[i].next){
    		if((y=edge[i].to)==fa[x])continue;
    		dfs1(y,x),sz[x]+=sz[y];
    		if(sz[son[x]]<sz[y])son[x]=y;
    	}
    }
    void dfs2(int x){
    	if(son[x])top[son[x]]=top[x],dfn[son[x]]=++tot,rev[tot]=son[x],dfs2(son[x]);
    	for(int i=head[x],y;i!=-1;i=edge[i].next){
    		y=edge[i].to;
    		if(y==fa[x]||y==son[x])continue;
    		top[y]=y,dfn[y]=++tot,rev[tot]=y,dfs2(y);
    	}
    }
    //--------------Persistent Segment Tree--------------------
    #define mid ((l+r)>>1)
    int rt[N],newid;
    struct SegTree{
    	int lson,rson,sum;
    }seg[20001000];
    void build(int &x,int l,int r){
    	x=++newid;
    	if(l!=r)build(seg[x].lson,l,mid),build(seg[x].rson,mid+1,r);
    }
    void modify(int &x,int y,int l,int r,int P){
    	if(l>P||r<P)return;
    	seg[x=++newid]=seg[y],seg[x].sum++;
    	if(l!=r)modify(seg[x].lson,seg[y].lson,l,mid,P),modify(seg[x].rson,seg[y].rson,mid+1,r,P);
    }
    int asksize(int x,int l,int r,int L,int R){
    	if(l>R||r<L)return 0;
    	if(L<=l&&r<=R)return seg[x].sum;
    	return asksize(seg[x].lson,l,mid,L,R)+asksize(seg[x].rson,mid+1,r,L,R);
    }
    int rangeask(int x,int y,int l,int r,int k){
    	if(l==r)return rev[l];
    	if((mid-l+1)-(seg[seg[y].lson].sum-seg[seg[x].lson].sum)>=k)return rangeask(seg[x].lson,seg[y].lson,l,mid,k);
    	else return rangeask(seg[x].rson,seg[y].rson,mid+1,r,k-((mid-l+1)-(seg[seg[y].lson].sum-seg[seg[x].lson].sum)));
    }
    int askkth(int x,int y,int l,int r,int L,int R,int &k,bool &findans){
    	if(l>R||r<L)return 0;
    	if(L<=l&&r<=R){
    		if((r-l+1)-(seg[y].sum-seg[x].sum)>=k){findans=true;return rangeask(x,y,l,r,k);}
    		else{k-=(r-l+1)-(seg[y].sum-seg[x].sum);return 0;};
    	}
    	int tmp=askkth(seg[x].lson,seg[y].lson,l,mid,L,R,k,findans);
    	if(findans)return tmp;
    	return askkth(seg[x].rson,seg[y].rson,mid+1,r,L,R,k,findans);
    }
    #define AS(A,B,L,R) (R-L+1)-(asksize(rt[B],1,n,L,R)-asksize(rt[A],1,n,L,R))
    int main(){
    	scanf("%d",&n),memset(head,-1,sizeof(head));
    	for(int i=1,x;i<=n;i++){
    		scanf("%d",&x);
    		if(x)ae(x,i);
    	}
    	dfs1(1,0),top[1]=dfn[1]=rev[1]=tot=1,dfs2(1);
    	build(rt[0],1,n);
    	scanf("%d",&m);
    	for(int i=1,a,b,c,d,tp,res;i<=m;i++){
    		scanf("%d",&tp);
    		if(tp==1)scanf("%d",&a),des[a]=i,modify(rt[i],rt[i-1],1,n,dfn[a]);
    		else{
    			rt[i]=rt[i-1],res=0;
    			scanf("%d%d%d%d",&a,&b,&c,&d);
    			if(des[a]<=d)c++;
    			int x=a,y=b,len=0;
    			while(top[x]!=top[y]){
    				if(dep[top[x]]<dep[top[y]])swap(x,y);
    				len+=AS(d,i,dfn[top[x]],dfn[x]),x=fa[top[x]];
    			}
    			if(dep[x]>dep[y])swap(x,y);
    			len+=AS(d,i,dfn[x],dfn[y]);
    			len-=(des[b]<=d);
    			if(len<c){puts("-1");continue;}
    //---------------------getpath&LCA-------------------------			
    			int LCA=x;
    			x=a;
    			bool getans=false;
    			while(dep[x]>=dep[LCA]){
    				int anc=(dep[top[x]]<dep[LCA]?LCA:top[x]);
    				int tmp=AS(d,i,dfn[anc],dfn[x]);
    				if(c>tmp)c-=tmp,len-=tmp;
    				else{c=tmp-c+1;res=askkth(rt[d],rt[i],1,n,dfn[anc],dfn[x],c,getans);break;}
    				x=fa[top[x]];
    			}
    			if(getans){printf("%d\n",res);continue;}
    //--------------------check A-----------------------------
    			y=b;
    			c=len-c+1;
    			if(des[b]<=d)c++;
    			while(true){
    				int dfntop=dfn[top[y]];
    				if(dep[top[y]]<=dep[LCA])dfntop=dfn[LCA]+1;
    				int tmp=AS(d,i,dfntop,dfn[y]);
    				if(c>tmp)c-=tmp;
    				else{c=tmp-c+1;res=askkth(rt[d],rt[i],1,n,dfntop,dfn[y],c,getans);break;}
    				y=fa[top[y]];
    			}
    			printf("%d\n",res);
    		}
    	}
    	return 0;
    } 
    

  • 相关阅读:
    最近要看的项目
    Lavarel Route::resource
    架构,性能
    Unity ToLua & LuaFramework_UGUI学习笔记(zz)
    Unity UI 布局
    Introduction to Unity UI
    Unity more efficient find
    unity UI如何开启(显示)或者关闭(隐藏)Panel界面最好?
    Unity Canvas vs Panel
    Unity实现新手引导圆形遮罩
  • 原文地址:https://www.cnblogs.com/Troverld/p/14611241.html
Copyright © 2011-2022 走看看