链接: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;
}