码迷,mamicode.com
首页 > 其他好文 > 详细

spoj3267 D-query 主席树(可持久化线段树)

时间:2015-04-04 16:47:47      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:主席树

题目链接

题意:给n个数,m次查询,求[l,r]之间不重复数的个数。

思路:主席树。用一个map记录每个值在当前操作下最新的位置,从前往后插入主席树。对于查询[l,r],窝们在root[ l ]下查询在r之前的不重复数的个数。详见代码:

/*********************************************************
  file name: spoj3267.cpp
  author : kereo
  create time:  2015年04月04日 星期六 14时29分56秒
*********************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=100+50;
const int MAXN=30000+50;
const int inf=0x3fffffff;
const double eps=1e-8;
const int mod=1000000000+7;
#define L(x) (x->ch[0])
#define R(x) (x->ch[1])
#define PII pair<int, int>
#define mk(x,y) make_pair((x),(y))
int n,m,cnt,top;
int a[MAXN],st[MAXN*30];
struct node{
	int num;
	node *ch[2];
}nod[MAXN*30],*root[MAXN],nil,*null;
map<int,int>mp;
struct CMT{
	void init(){
		cnt=top=0;
		nil.num=0; null=&nil;
		L(null)=R(null)=null;
		for(int i=0;i<=n+1;i++)
			root[i]=null;
	}
	void newnode(node * &x,node *fa,int val){
		if(top)
			x=&nod[st[--top]];
		else
			x=&nod[cnt++];
		if(fa == null){
			x->num=val;
			L(x)=R(x)=null;
		}
		else{
			x->num=fa->num+val;
			L(x)=L(fa); R(x)=R(fa);
		}
	}
	void insert(node *&rt,node *fa,int l,int r,int pos,int val){
		newnode(rt,fa,val);
		if(l == r)
			return ;
		int mid=(l+r)>>1;
		if(pos<=mid)
			insert(L(rt),L(fa),l,mid,pos,val);
		else 
			insert(R(rt),R(fa),mid+1,r,pos,val);
	}
	int query(node *rt,int pos){
		int l=1,r=n,ans=0;
		while(pos<r){
			int mid=(l+r)>>1;
			if(pos<=mid){
				rt=L(rt);
				r=mid;
			}
			else{
				ans+=L(rt)->num;
				rt=R(rt); l=mid+1;
			}
		}
		return ans+rt->num;
	}
}cmt;
int main(){
	//freopen("in.txt","r",stdin);
	while(~scanf("%d",&n)){
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		cmt.init(); mp.clear();
		for(int i=n;i>=1;i--){
			if(mp.find(a[i]) == mp.end())
				cmt.insert(root[i],root[i+1],1,n,i,1);
			else{
				cmt.insert(root[0],root[i+1],1,n,mp[a[i]],-1);
				cmt.insert(root[i],root[0],1,n,i,1);
			}
			mp[a[i]]=i;
		}
		scanf("%d",&m);
		while(m--){
			int l,r;
			scanf("%d%d",&l,&r);
			printf("%d\n",cmt.query(root[l],r));
		}
	}
	return 0;
}

spoj3267 D-query 主席树(可持久化线段树)

标签:主席树

原文地址:http://blog.csdn.net/u011645923/article/details/44873369

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!