• 【题解】Count on a tree


    Count on a tree

    ( ext{Solution:})

    就是一个树上静态第 (k) 小。

    考虑对于一个点 (x) 维护一棵主席树,它的信息是 ([root,x].)

    这样对于一条路径 (<s,t>) ,它的信息可以用树上差分的思想来统计:

    [cnt=root[s]+root[t]-root[LCA]-root[pa[LCA]] ]

    有了这个式子就好办了,树剖 LCA 套上树上差分即可。

    时间复杂度 (O(nlog n).)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int MAXN=2e5+10;
    const int N=(MAXN<<5);
    int rt[MAXN],node,siz[MAXN],pa[MAXN];
    struct Tr{int ls,rs,sum;}tr[N];
    int head[MAXN],tot,top[MAXN],son[MAXN];
    struct E{int nxt,to;}e[MAXN];
    inline void add(int x,int y){e[++tot]=(E){head[x],y};head[x]=tot;}
    int b[MAXN],blen,n,m,a[MAXN],lastans,dep[MAXN];
    inline int Min(int x,int y){return x<y?x:y;}
    inline int Max(int x,int y){return x>y?x:y;}
    inline int read() {
    	int s=0,w=1;
    	char ch=getchar();
    	while(!isdigit(ch)) {
    		if(ch=='-')w=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)) {
    		s=s*10-48+ch;
    		ch=getchar();
    	}
    	return w*s;
    }
    inline int getpos(int v){return lower_bound(b+1,b+blen+1,v)-b;}
    int change(int x,int l,int r,int pos,int v){
    	int p=++node;
    	tr[p]=tr[x];
    	tr[p].sum+=v;
    	if(l==r)return p;
    	int mid=(l+r)>>1;
    	if(pos<=mid)tr[p].ls=change(tr[p].ls,l,mid,pos,v);
    	else tr[p].rs=change(tr[p].rs,mid+1,r,pos,v);
    	return p;
    }
    int query(int x,int y,int l,int fl,int L,int R,int k){
    	//cnt=x+y-l-fl
    	if(L==R)return L;
    	int mid=(L+R)>>1;
    	int cnt=tr[tr[x].ls].sum+tr[tr[y].ls].sum-tr[tr[l].ls].sum-tr[tr[fl].ls].sum;
    	if(k<=cnt)return query(tr[x].ls,tr[y].ls,tr[l].ls,tr[fl].ls,L,mid,k);
    	else return query(tr[x].rs,tr[y].rs,tr[l].rs,tr[fl].rs,mid+1,R,k-cnt);
    }
    void dfs1(int x){
    	siz[x]=1;dep[x]=dep[pa[x]]+1;
    	for(int i=head[x];i;i=e[i].nxt){
    		int j=e[i].to;
    		if(j==pa[x])continue;
    		pa[j]=x;
    		dfs1(j);siz[x]+=siz[j];
    		if(siz[j]>siz[son[x]])son[x]=j;
    	}
    }
    void dfs2(int u,int t){
    	top[u]=t;
    	if(!son[u])return;
    	dfs2(son[u],t);
    	for(int i=head[u];i;i=e[i].nxt){
    		int j=e[i].to;
    		if(j==pa[u]||j==son[u])continue;
    		dfs2(j,j);
    	}
    }
    int LCA(int x,int y){
    	while(top[x]!=top[y]){
    		if(dep[top[x]]>=dep[top[y]])x=pa[top[x]];
    		else y=pa[top[y]];
    //		cout<<x<<" "<<y<<endl;
    	}
    	return dep[x]<dep[y]?x:y;
    }
    void dfs(int x,int fa){
    	rt[x]=change(rt[fa],1,blen,a[x],1);
    	for(int i=head[x];i;i=e[i].nxt){
    		int j=e[i].to;
    		if(j==fa)continue;
    		dfs(j,x);
    	}
    }
    signed main(){
    //	freopen("P2633_1.in","r",stdin);
    //	freopen("my.out","w",stdout);
    	n=read(),m=read();
    	for(int i=1;i<=n;++i)a[i]=read(),b[i]=a[i];
    	sort(b+1,b+n+1);
    	blen=unique(b+1,b+n+1)-b-1;
    	for(int i=1;i<=n;++i)a[i]=getpos(a[i]);
    //	for(int i=1;i<=n;++i)printf("%d ",a[i]);
    //	puts("");
    	for(int i=1;i<n;++i){
    		int u=read(),v=read();
    		add(u,v);add(v,u);
    	}
    	dfs1(1);dfs2(1,1);dfs(1,1);
    	//puts("RE!");return 0;
    //	for(int i=1;i<=n;++i)printf("%d:dep%d,siz%d
    ",i,dep[i],siz[i]);
    	for(int i=1;i<=m;++i){
    		int u=read(),v=read(),k=read();
    		u^=lastans;
    //		printf("(%lld %lld)
    ",u,v);
    		int Lca=LCA(u,v);
    //		printf("LCA:%lld
    ",Lca);
    		lastans=b[query(rt[u],rt[v],rt[Lca],rt[pa[Lca]],1,blen,k)];
    		printf("%lld
    ",lastans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    将cvs迁移到svn
    wincvs,cvs,svn
    Open Source Camp 北京 2008技术交流盛会 感悟
    21,22,23,24日外出纪要
    10.31,11.1外出纪要
    虚拟经济区一行有感
    29,30号活动预告
    ror 2.1.2migration
    netbeans 6.5 release
    [转载]ruby on rails 每周精选二
  • 原文地址:https://www.cnblogs.com/h-lka/p/14965548.html
Copyright © 2020-2023  润新知