CCPC网络赛 HDU-6703 array(主席树+set+思维)(查询区间内第一个大于等于k的数模板)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6703

题意:多组样例。给出1~n的全排列,m个操作,操作有两种,第一种将a[pos]+1e7;第二种询问不是[1,r]区间内的并不小于k的数。强制在线查询。

思路:由于n小于1e5,且每个数加的是1e7,第一种操作的数,相当于删去该数。每次第二种操作答案的范围为[1,n+1]。这个答案要么在之前第一种操作删去的数中,要么在[r+1,n]这个区间内的数中,每次找出来再和n+1取个最小值即可。

PS:%坤神,tqltqltqltql。另外他的模板真好用。

#include
#include
#include
#include
#include
#include 
using namespace std;
#define M(a, b) memset(a, b, sizeof(a))
#define lowbit(x) (x&(-x))
typedef long long ll;
const int N=1e5+10;
 
struct node
{
    int l,r;
    int val;
}tree[N*22];
int n,q,a[N],root[N],cnt,temp;
set s;
set::iterator it;
inline int read()     
{
    int res=0,ch,flag=0;
    if((ch=getchar())=='-')
        flag=1;
    else if(ch>='0'&&ch<='9')
        res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
    return flag?-res:res;
}
inline void write(int a)    
{
    if(a>9)
        write(a/10);
    putchar(a%10+'0');
}
inline int update(int up,int tar,int l,int r)
{
    int cur=cnt++;//增加新端点,为期编号 
    tree[cur]=tree[up];//先用上一个树的节点信息 
    tree[cur].val++;
    if(l==r) return cur;
    int mid=(r+l)>>1;
    //更新新建树的节点信息 
    if(tar<=mid) tree[cur].l=update(tree[up].l,tar,l,mid);
    else tree[cur].r=update(tree[up].r,tar,mid+1,r);
    return cur;
}
//询问[pl,pr]内大于tar的第一个数 
inline int query(int pl,int pr,int l,int r,int tar)
{
    if(l==r) return l;
    int mid=(r+l)>>1,lnum,rnum,res=N;
	lnum=tree[tree[pr].l].val-tree[tree[pl].l].val;
	rnum=tree[tree[pr].r].val-tree[tree[pl].r].val;
	//如果tar这个数在[l,r]内 
	if(tar>=l)
	{
		//如果要查的数在[l,mid]区间内,并且左子树上数的个数不为0 
		if(tar<=mid&&lnum>0)
		{
			temp=query(tree[pl].l,tree[pr].l,l,mid,tar);
			if(temp0)
		{
			temp=query(tree[pl].r,tree[pr].r,mid+1,r,tar);
			res=min(res,temp);	
		} 		
	}
	//tar这个数小于l 
	else
	{
		//如果左子树上数的个数不为0 
		if(lnum>0)
		{
			temp=query(tree[pl].l,tree[pr].l,l,mid,tar);
			if(temp0)
		{
			temp=query(tree[pl].r,tree[pr].r,mid+1,r,tar);
			res=min(res,temp);
		} 
	}
	return res;
}
int main()
{
	int t,ans,op,pos,r,k,ans1,ans2;
	t=read();//scanf("%d",&t);
    while(t--)
    {
    	n=read(),q=read();//scanf("%d%d",&n,&q); 
    	s.clear();
    	cnt=0; 
    	ans=0;
        for(int i=1;i<=n;i++)
        {
        	a[i]=read();//scanf("%d",&a[i]);
        	root[i]=update(root[i-1],a[i],1,n);
		}            
        while(q--)
        {
            op=read();//scanf("%d",&op);
			if(op==1)
			{
				pos=read();//scanf("%d",&pos);
				pos^=ans;
				s.insert(a[pos]);
			}
			else
			{
				r=read(),k=read();//scanf("%d%d",&r,&k);
				r^=ans,k^=ans;
				ans1=n+1,ans2=n+1;
				
				it=s.lower_bound(k);
				if(it!=s.end()) ans1=*it;
				
				if(r!=n)
				{
					temp=query(root[r],root[n],1,n,k);
					if(ans2>temp)
						ans2=temp;
				}	
				write(ans=min(ans1,ans2));
				putchar('\n');	
				//printf("%d\n",ans=min(ans1,ans2));
			}
	    }
    }
 
	return 0;
}

 

 

你可能感兴趣的:(=====数据结构=====,=====模板=====)