主席树

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\n",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<<"#\n";
	ll ret=0;
	ret += T.query(L,R,T.root[f],T.root[u],1,n);
	//cout<<ret<<"#\n";
	ret += T.query(L,R,T.root[ff],T.root[v],1,n);
	//cout<<ret<<"#\n";
	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," \n"[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\n",x,k);
        la=T.query(dep[x],min(dep[x]+k,n),T.root[x],T.root[x],1,n);
        printf("%d\n",la);
    }
    return 0;
}
posted @ 2017-11-21 15:48  foreignbill  阅读(148)  评论(0编辑  收藏  举报