主席树模板

区间第K大:POJ-2104

#include
#include
#include
#include
using namespace std;
const int maxn=1e5+1000;
int cnt,root[maxn],n,m;
int a[maxn];
vector v;
struct node
{
	int l,r,sum;
}tree[maxn*40]; 
int getid(int x)
{
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void insert(int l,int r,int &x,int y,int pos)
{
	tree[++cnt]=tree[y];tree[cnt].sum++,x=cnt;
	if(l==r) return ;
	int m=(l+r)>>1;
	if(pos<=m) insert(l,m,tree[x].l,tree[y].l,pos);
	else insert(m+1,r,tree[x].r,tree[y].r,pos);
}
int query(int l,int r,int x,int y,int k)
{
	if(l==r) return l;
	int m=(l+r)>>1;
	int sum=tree[tree[y].l].sum-tree[tree[x].l].sum;
	if(sum>=k){
		return query(l,m,tree[x].l,tree[y].l,k);
	}
	else return query(m+1,r,tree[x].r,tree[y].r,k-sum);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]),v.push_back(a[i]);
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
	int sz=v.size();
	for(int i=1;i<=n;i++) insert(1,sz,root[i],root[i-1],getid(a[i]));	
	while(m--)
	{
		int x,y,k;
		scanf("%d%d%d",&x,&y,&k);
		printf("%d\n",v[query(1,sz,root[x-1],root[y],k)-1]);
	}
	return 0;
}

树上第K小:SPOJ-COT

#include
using namespace std;
const int maxn=1e5+1000;
int a[maxn];
struct node
{
	int l,r,sum;
}tree[maxn*40];
int cnt,root[maxn];
vector v[maxn],v1;
int num[maxn],fa[maxn][30],depth[maxn];
int n,m,sz;
int getid(int x){
	return lower_bound(v1.begin(),v1.end(),x)-v1.begin()+1;
} 
//void build(int l,int r,int &rt)
//{
//	rt=++cnt;
//	tree[rt].sum=0;
//	if(l==r) return ;
//	int m=(l+r)>>1;
//	build(l,m,tree[rt].l);
//	build(m+1,r,tree[rt].r); 
//} 
void update(int l,int r,int &x,int y,int pos){
	tree[++cnt]=tree[y];tree[cnt].sum++;x=cnt;
	if(l==r) return ;
	int m=(l+r)>>1;
	if(pos<=m) update(l,m,tree[x].l,tree[y].l,pos);
	else update(m+1,r,tree[x].r,tree[y].r,pos);
}
int query(int l,int r,int x,int y,int z,int w,int k){
	if(l==r) return l;
	int m=(l+r)>>1;
	int tmp=tree[tree[x].l].sum+tree[tree[y].l].sum-tree[tree[z].l].sum-tree[tree[w].l].sum;
	if(tmpdepth[b]) swap(a,b);
	int f=depth[b]-depth[a];
	for(int j=0;(1<=0;i--){
		if(fa[a][i]!=fa[b][i]){
			a=fa[a][i],b=fa[b][i];
		}
	}
	return fa[a][0];
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]),v1.push_back(a[i]);
	sort(v1.begin(),v1.end());
	v1.erase(unique(v1.begin(),v1.end()),v1.end());
	for(int i=1;i

区间不同值:SPOJ - DQUERY

#include
using namespace std;
const int maxn=1e5+100;
int root[maxn],cnt;
struct node
{
	int l,r,num;
 }tree[maxn*40];
int a[maxn];
map ma;
int sz=maxn; 
void insert(int l,int r,int &x,int y,int pos,int v)
{
	tree[++cnt]=tree[y];tree[cnt].num+=v;x=cnt;
	if(l==r) return ;
	int m=(l+r)>>1;
	if(pos<=m) insert(l,m,tree[x].l,tree[y].l,pos,v);
	else insert(m+1,r,tree[x].r,tree[y].r,pos,v);
}
int query(int l,int r,int L,int R,int y)
{
	if(L<=l&&r<=R) return tree[y].num;
	int m=(l+r)>>1;
	int ans=0;
	if(L<=m) ans+=query(l,m,L,R,tree[y].l);
	if(R>m) ans+=query(m+1,r,L,R,tree[y].r);
	return ans;
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=n;i++){
		if(ma[a[i]]==0){
			insert(1,sz,root[i],root[i-1],i,1);//在第i个位置插入 保证线段树上区间也对应 
			ma[a[i]]=i;
		} 
		else{
			insert(1,sz,root[i],root[i-1],ma[a[i]],-1);
			ma[a[i]]=i;
			insert(1,sz,root[i],root[i],i,1);
		}
	}
	int m;
	cin>>m;
	while(m--)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		printf("%d\n",query(1,sz,x,y,root[y]));//0-root[y]即可 
	}
	return 0;
}

区间第k大+区间不同值:HDU - 5919

#include
#include
#include
#include
#include
using namespace std;
const int maxn=2e5+1000;
struct node{
	int l,r,num;
}tree[maxn*40];
int root[maxn],tot;
int a[maxn];
int sz=maxn;
void update(int l,int r,int &x,int y,int pos,int val)
{
	x=++tot;tree[x]=tree[y];tree[x].num+=val;
	if(l==r) return ;
	int m=(l+r)>>1;
	if(pos<=m) update(l,m,tree[x].l,tree[y].l,pos,val);
	else update(m+1,r,tree[x].r,tree[y].r,pos,val); 
}
int query1(int l,int r,int y,int L,int R)
{
	if(L<=l&&r<=R)
	{
		return tree[y].num;
	}
	int m=(l+r)>>1;
	int ans=0;
	if(L<=m) ans+=query1(l,m,tree[y].l,L,R);
	if(R>m) ans+=query1(m+1,r,tree[y].r,L,R);
	return ans; 
}
int query2(int l,int r,int y,int k)
{
	if(l==r) return l;
	int m=(l+r)>>1;
	int tmp=tree[tree[y].l].num;
	if(k>tmp) return query2(m+1,r,tree[y].r,k-tmp);
	else return query2(l,m,tree[y].l,k); 
}
int main()
{
	int kase;
	scanf("%d",&kase);
	int cc=0;
	while(kase--)
	{
		int lastans=0;
		tot=0;
		memset(root,0,sizeof(root));
		memset(tree,0,sizeof(tree));
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		map ma; 
		for(int i=n;i>=1;i--)
		{
			if(ma[a[i]]==0){
				update(1,sz,root[i],root[i+1],i,1);
			}else{	
				
				update(1,sz,root[i],root[i+1],ma[a[i]],-1);
				update(1,sz,root[i],root[i],i,1);
			}
			ma[a[i]]=i;
		}
		printf("Case #%d: ",++cc);
		while(m--)
		{
			int l,r;
			scanf("%d%d",&l,&r);
			int ll=l;
			l=min((l+lastans)%n+1,(r+lastans)%n+1);
			r=max((ll+lastans)%n+1,(r+lastans)%n+1);
			int k=query1(1,sz,root[l],l,r); 
			lastans=query2(1,sz,root[l],ceil(1.0*k/2)); 
			printf("%d",lastans);
			if(m==0) puts("");
			else printf(" ");
		}
	}
	return 0;
 } 

主席树区间更新:HDU - 4348

#include 
#include
#include
#include
using namespace std;
const int maxn=1e5+1000;
typedef long long ll;
int a[maxn];
struct node
{
	int l,r;
	ll sum,lazy;
}tree[maxn*40];
int root[maxn],tot;
int n,m;
int sz=maxn;
void build(int l,int r,int &x)
{
	x=++tot;
	tree[x].sum=0;
	tree[x].lazy=0;
	if(l==r)
	{
		tree[x].sum+=a[l];
		return ;
	 } 
	 int m=(l+r)>>1;
	 build(l,m,tree[x].l);
	 build(m+1,r,tree[x].r);
	tree[x].sum=tree[tree[x].l].sum+tree[tree[x].r].sum;
}
void update(int l,int r,int L,int R,int &x,int y,int val)
{
	x=++tot;
	tree[x]=tree[y];
	tree[x].sum+=1ll*val*(min(R,r)-max(l,L)+1);
	if(L<=l&&r<=R){
		tree[x].lazy+=val;
		return ;
	}
	int m=(l+r)>>1;
	if(L<=m) update(l,m,L,R,tree[x].l,tree[y].l,val);
	if(R>m) update(m+1,r,L,R,tree[x].r,tree[y].r,val);
}
ll query(int l,int r,int L,int R,int x,ll lazy)
{
	if(L<=l&&r<=R){	
		return tree[x].sum+lazy*(r-l+1);

	}
	ll ans=0;
	int m=(l+r)>>1;
	if(L<=m) ans+=query(l,m,L,R,tree[x].l,lazy+tree[x].lazy);
	if(R>m) ans+=query(m+1,r,L,R,tree[x].r,lazy+tree[x].lazy);
	return ans;
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		tot=0;
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		int p=0;
		build(1,sz,root[p]);
		while(m--)
		{
			char op[10];
			scanf("%s",op);
			if(op[0]=='Q'){
				int l,r;
				scanf("%d%d",&l,&r);
				printf("%lld\n",query(1,sz,l,r,root[p],0));
			} 
			else if(op[0]=='C'){
				int l,r,d;
				scanf("%d%d%d",&l,&r,&d);
				update(1,sz,l,r,root[p+1],root[p],d);
				p++;
			}
			else if(op[0]=='B'){
				int t;
				scanf("%d",&t);
				p=t;
			}
			else if(op[0]=='H'){
				int l,r,t;
				scanf("%d%d%d",&l,&r,&t);
				printf("%lld\n",query(1,sz,l,r,root[t],0));
			}
		}
	}
	return 0;
}

 

你可能感兴趣的:(算法,模板,主席树模板)