• BZOJ2588 Spoj 10628. Count on a tree


    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:BZOJ2588

         SPOJ10628

    正解:主席树上树

    解题报告:

      考虑主席树上树,每次build都是儿子在父亲的基础上build,然后查询的话就是对于x到y的路径,令$Tx$为$x$对应的线段树,那就是$T_x+T_y-T_{lca}-T_{fa[lca]}$。

      

    //It is made by ljh2000
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <complex>
    using namespace std;
    #define lc t[R].ls
    typedef long long LL;
    typedef long double LB;
    typedef complex<double> C;
    const double pi = acos(-1);
    const int MAXN = 200011;
    const int MAXM = 400011;
    int n,m,ecnt,first[MAXN],to[MAXM],next[MAXM],deep[MAXN],ans;
    int a[MAXN],b[MAXN],c[MAXN],L,f[MAXN][18],cnt,root[MAXN];
    inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
    struct node{
    	int ls,rs,num;
    }t[7000011];
    
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void build(int &rt,int last,int l,int r,int pos){
    	rt=++cnt; t[rt]=t[last]; t[rt].num++;
    	if(l==r) return ; int mid=(l+r)>>1;
    	if(pos<=mid) build(t[rt].ls,t[last].ls,l,mid,pos);
    	else build(t[rt].rs,t[last].rs,mid+1,r,pos);
    }
    
    inline void dfs(int x,int fa){
    	build(root[x],root[fa],1,L,c[x]);//以父亲节点为last,更新主席树
    	//printf("%d
    ",cnt);
    	for(int i=first[x];i;i=next[i]) {
    		int v=to[i]; if(v==fa) continue;
    		f[v][0]=x; deep[v]=deep[x]+1;
    		dfs(v,x);
    	}
    }
    
    inline int lca(int x,int y){
    	if(deep[x]<deep[y]) swap(x,y); int t=0; while((1<<t)<=deep[x]) t++; t--;
    	for(int i=t;i>=0;i--) if(deep[x]-(1<<i)>=deep[y]) x=f[x][i]; if(x==y) return y;
    	for(int i=t;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0];
    }
    
    inline int query(int x1,int x2,int j1,int j2,int l,int r,int k){
    	if(l==r) return l;
    	int R=x1; int cp=t[lc].num; int mid=(l+r)>>1;
    	R=x2; cp+=t[lc].num;
    	R=j1; cp-=t[lc].num;
    	R=j2; cp-=t[lc].num;
    	if(k<=cp) return query(t[x1].ls,t[x2].ls,t[j1].ls,t[j2].ls,l,mid,k);
    	else return query(t[x1].rs,t[x2].rs,t[j1].rs,t[j2].rs,mid+1,r,k-cp);
    }
    
    inline void work(){
    	n=getint(); m=getint(); for(int i=1;i<=n;i++) b[i]=a[i]=getint();
    	sort(b+1,b+n+1); L=unique(b+1,b+n+1)-b-1; 
    	for(int i=1;i<=n;i++)
    		c[i]=lower_bound(b+1,b+L+1/*!!!*/,a[i])-b;
    
    	int x,y,z,G; ans=0;
    	for(int i=1;i<n;i++) { x=getint(); y=getint(); link(x,y); link(y,x); }
    	deep[1]=1; dfs(1,0);
    	for(int j=1;j<=17;j++)
    		for(int i=1;i<=n;i++)
    			f[i][j]=f[f[i][j-1]][j-1];
    
    	while(m--) {
    		x=getint(); y=getint(); z=getint();	x^=ans;
    		G=lca(x,y);
    		ans=b[ query(root[x],root[y],root[G],root[ f[G][0] ],1,L,z) ];
    		printf("%d",ans);
    		if(m!=0) puts("");
    	}
    }
    
    int main()
    {
        work();
        return 0;
    }
    

      

  • 相关阅读:
    剑指Offer
    剑指Offer
    剑指Offer
    选书
    马的遍历
    从事效应
    魔性的素数环1~20 自带解释~
    [POJ1236]Network of Schools(并查集+floyd,伪强连通分量)
    [HDOJ3974]Assign the task(建树胡搞)
    [HDOJ4027]Can you answer these queries?(线段树,特殊成段更新,成段查询)
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6502101.html
Copyright © 2020-2023  润新知