• 主席树


    Hdu 2665

    区间K小

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5+5;
    int arr[maxn];
    int Rank[maxn];
    
    struct ChairTree{
        #define lson tree[rt].lc,tree[rt1].lc,l,m
        #define rson tree[rt].rc,tree[rt1].rc,m+1,r
        struct node{
            int lc,rc,w;
            node(){}
        }tree[maxn*20];
        int root[maxn],cnt;
        void init(){
            root[0]=cnt=0;
            memset(tree,0,sizeof tree);
        }
    
        void add(int pos,int val,int &rt,int rt1,int l,int r){
            tree[rt = ++cnt] = tree[rt1];
            tree[rt].w += val;  
            if(l==r) return;
            int m=(l+r)/2;
            if(pos<=m) add(pos,val,lson);
            else add(pos,val,rson);
        }
    
        int query(int k,int rt,int rt1,int l,int r){
            if(l==r) return l;
            int lsize = tree[tree[rt1].lc].w-tree[tree[rt].lc].w;
            int m=(l+r)/2;
            if(lsize>=k) return query(k,lson);
            else return query(k-lsize,rson);
        }
    }T;
    
    int main(){
        //freopen("in.txt","r",stdin);
        int cas,n,q,l,r,k;
        for(cin>>cas;cas--;){
            T.init();
            scanf("%d%d",&n,&q);
            for(int i=1;i<=n;i++){
                scanf("%d",&arr[i]);
                Rank[i]=arr[i];
            }
            sort(Rank+1,Rank+1+n);
            int un=unique(Rank+1,Rank+1+n)-(Rank+1);
            for(int i=1;i<=n;i++){
                arr[i]=lower_bound(Rank+1,Rank+1+un,arr[i])-Rank;
            }
            for(int i=1;i<=n;i++){
                T.add(arr[i],1,T.root[i],T.root[i-1],1,un);
            }
            while(q--){
                scanf("%d%d%d",&l,&r,&k);
                int pos = T.query(k,T.root[l-1],T.root[r],1,un);
                printf("%d
    ",Rank[pos]);
            }
        }
        return 0;
    }
    

    hdu 6162

    多校9的题,因为数据弱水过去了。
    考虑主席树,用dfs的方式建立主席树。
    设$lca(u,v)=f$,那么路径就是f到u+f到v的满足条件的和。
    主席树区间查询。那么答案就是f到u和fa[f]到v。

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5+5;
    int arr[maxn];
    int Rank[maxn];
    vector<int> e[maxn];
    int dep[maxn],fa[maxn][18];
    int cas,n,q,l,r,k;
    
    struct ChairTree{
    	#define sum(x) tree[x].sum
    	#define lson tree[rt].lc,tree[rt1].lc,l,m
    	#define rson tree[rt].rc,tree[rt1].rc,m+1,r
    	struct node{
    		int lc,rc;
    		ll sum;
    		node(){}
    	}tree[maxn*20];
    	int root[maxn],cnt,n;
    	void init(int _n){
    		n=_n;
    		root[0]=cnt=0;
    		memset(tree,0,sizeof tree);
    	}
    
    	void add(int pos,int val,int &rt,int rt1,int l,int r){
    		tree[rt = ++cnt] = tree[rt1];
            tree[rt].sum += val;	
    		if(l==r) return;
    		int m=(l+r)/2;
    		if(pos<=m) add(pos,val,lson);
    		else add(pos,val,rson);
    	}
    
    	ll query(int L,int R,int rt,int rt1,int l,int r){
    		if(L<=l&&r<=R) return sum(rt1)-sum(rt);
    		if(0==sum(rt1)) return 0;
    		ll ret=0;
    		int m=(l+r)/2;
    		if(L<=m) ret+=query(L,R,lson);
    		if(m< R) ret+=query(L,R,rson);
    		return ret;
    	}
    }T;
    
    void dfs(int id,int father){
    	T.add(arr[id],Rank[arr[id]],T.root[id],T.root[father],1,n);
    	fa[id][0]=father;
    	dep[id]=dep[father]+1;
    	for(int i=1;i<=17;i++){
    		if(dep[id]<(1<<i)) break;
    		fa[id][i]=fa[fa[id][i-1]][i-1];
    	}
    	for(auto ep:e[id]){
    		if(ep==father) continue;
    		dfs(ep,id);
    	}
    }
    
    int lca(int x,int y){
    	if(dep[x]<dep[y]) swap(x,y);
    	int t=dep[x]-dep[y];
    	for(int i=0;i<=17;i++) if((1<<i)&t) x=fa[x][i];
    	for(int i=17;i>=0;i--)
    		if(fa[x][i]!=fa[y][i]){
    			x=fa[x][i];y=fa[y][i];
    		}
    	return x==y?x:fa[x][0];
    }
    
    ll solve(int u,int v,int L,int R){
    	int f=lca(u,v);
    	int ff=fa[f][0];
    	//cout<<ff<<"#
    ";
    	ll ret=0;
    	ret += T.query(L,R,T.root[f],T.root[u],1,n);
    	//cout<<ret<<"#
    ";
    	ret += T.query(L,R,T.root[ff],T.root[v],1,n);
    	//cout<<ret<<"#
    ";
    	return ret;
    }
    
    int main(){
    	//freopen("in.txt","r",stdin);
    	for(;~scanf("%d%d",&n,&q);){
    		for(int i=1;i<=n;i++){
    			scanf("%d",&arr[i]);
    			Rank[i]=arr[i];
    		}
    		sort(Rank+1,Rank+1+n);
    		int un=unique(Rank+1,Rank+1+n)-(Rank+1);
    		for(int i=1;i<=n;i++){
    			arr[i]=lower_bound(Rank+1,Rank+1+un,arr[i])-Rank;
    		}
    		for(int i=1;i<=n;i++)
    			e[i].clear();
    		memset(fa,0,sizeof fa);
    		memset(dep,0,sizeof dep);
    		for(int i=1;i<n;i++){
    			int u,v;
    			scanf("%d%d",&u,&v);
    			e[u].push_back(v);
    			e[v].push_back(u);
    		}
    		T.init(n);
    		dfs(1,0);
    		int u,v;
    		while(q--){
    			scanf("%d%d%d%d",&u,&v,&l,&r);
    			int L=lower_bound(Rank+1,Rank+1+un,l)-Rank;
    			if(Rank[L]<l) L++;
    			int R=lower_bound(Rank+1,Rank+1+un,r)-Rank;
    			if(R>un||Rank[R]>r) R--;
    			//cout<<"#"<<L<<" "<<R<<endl;
    			ll res=solve(u,v,L,R);
    			printf("%lld%c",res," 
    "[q==0]);
    		}
    	}
    	return 0;
    }
    

    Codeforces Edu 33 F

    主席树,按照dfs先后从根向前合并线段树。线段树维护dep的最小值。

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn = 1e6+7;
    int arr[maxn];
    int Rank[maxn],n,rtt;
    int dep[maxn];
    
    vector<int> e[maxn];
    
    struct ChairTree{
        #define lson tree[rt].lc,tree[rt1].lc,l,m
        #define rson tree[rt].rc,tree[rt1].rc,m+1,r
        struct node{
            int lc,rc,w;
            node(){}
        }tree[maxn*20];
        int root[maxn],cnt;
        void init(){
            root[0]=cnt=0;
            memset(tree,0,sizeof tree);
        }
        int merge(int rt,int rt1,int l,int r){
            if(!rt1) return rt;
            if(!rt) return rt1;
            int z=++cnt;
            if(l==r){
                tree[z].w=min(tree[rt].w,tree[rt1].w);
                return z;
            }
            int m=(l+r)/2;
            tree[z].lc=merge(lson);
            tree[z].rc=merge(rson);
            if(tree[z].lc||tree[z].rc) tree[z].w=min(tree[tree[z].lc].w,tree[tree[z].rc].w);
            else tree[z].w=min(tree[rt].w,tree[rt1].w);
            return z;
        }
    
        void add(int pos,int val,int &rt,int rt1,int l,int r){
    		rt=++cnt;
            if(l==r){
            	tree[rt].w=val;
            	return;
    		}
            int m=(l+r)>>1;
            if(pos<=m) add(pos,val,lson);
            else add(pos,val,rson);
            tree[rt].w=min(tree[tree[rt].lc].w,tree[tree[rt].rc].w);
        }
    
        int query(int L,int R,int rt,int rt1,int l,int r){
            if(L<=l&&r<=R) return tree[rt].w;
            int m=(l+r)/2;
            if(m>=R) return query(L,R,lson);
            else if(m<L) return query(L,R,rson);
            else return min(query(L,R,lson),query(L,R,rson));
        }
    }T;
    
    void dfs(int id,int fa){
        dep[id]=dep[fa]+1;
        T.add(dep[id],arr[id],T.root[id],T.root[fa],1,n);
        for(auto ep:e[id]){
            if(ep==fa) continue;
            dfs(ep,id);
            T.root[id]=T.merge(T.root[id],T.root[ep],1,n);
        }
    }
    
    int main(){
        //freopen("input.txt","r",stdin);
        T.tree[0].w=INT_MAX;
        scanf("%d%d",&n,&rtt);
        for(int i=1;i<=n;i++)
            scanf("%d",arr+i);
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            e[u].push_back(v);
            e[v].push_back(u);
        }
        dep[0]=0;
        dfs(rtt,0);
        int la=0,x,k;
        int m;
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&k);
            x=(x+la)%n+1;
            k=(k+la)%n;
            //printf("%d %d
    ",x,k);
            la=T.query(dep[x],min(dep[x]+k,n),T.root[x],T.root[x],1,n);
            printf("%d
    ",la);
        }
        return 0;
    }
    
  • 相关阅读:
    Beta冲刺阶段
    用例图练习
    第四次作业--个人作业--必应词典案例分析
    第五次作业——团队项目——需求规格说明书
    结对编程第三次作业
    第二次作业— —结对项目
    Git使用心得
    Android平台的开发环境的发展演变
    软件工程的实践项目的自我目标
    面试中遇到的问题
  • 原文地址:https://www.cnblogs.com/foreignbill/p/7873526.html
Copyright © 2020-2023  润新知