zoj月赛……只水了一道线段树的题目= =
第一题是很像线段树的YY题………虽然觉得区间合并貌似还是能做出来,不过区间合并还不是很懂= =!!
比赛的时候明明就看出来本质不是线段树的说……可是还是想用线段树做出来。。。
单点更新小变形,每个节点存区间里面还没被拿走的门票的个数,不懂可以刷一下http://www.notonlysuccess.com/index.php/segment-tree-complete/里面的单点更新专题,貌似有类似的
#include <iostream>
#include <cstdio>
#include <cstring>
#define lson l,mid,dex<<1
#define rson mid+1, r, dex<<1|1
#define havemid int mid = (l + r)/2
using namespace std;
const int maxx = 50010;
int key[maxx<<2];
int ans[maxx];
void build(int l, int r, int dex)
{
key[dex] = 1;
if(l==r) return;
havemid;
build(lson);
build(rson);
key[dex] = key[dex<<1] + key[dex<<1|1] ;
}
int updata(int l, int r, int dex, int& x)
{
if(l==r && key[dex])
{
x--;//如果这张门票存在,就把搜索数减一,直到x=0,表示要的就是这一张~
if(x==0)//于是这一张就标志没有了。
{
key[dex] = 0;
return l;
}
else
return 0;
}
havemid;
int tem;
if(x<=key[dex<<1])
tem = updata(lson,x);
else
{
x-=key[dex<<1];
tem = updata(rson,x);
}
key[dex] = key[dex<<1] + key[dex<<1|1];
return tem;
}
int main()
{
// freopen("1003.txt","r",stdin);
int n,m;
while(~scanf("%d",&n))
{
int w = 0;
build(1,n,1);
for(int i=1;i<=n;i++)
{
int tem;
scanf("%d",&tem);
int a = updata(1,n,1,tem);
ans[++w] = a;
}
scanf("%d",&m);
int vis = 0;
for(int i=1;i<=m;i++)
{
int tem = 0;
scanf("%d",&tem);
if(!vis)
{
printf("%d",ans[tem]);
vis = 1;
}
else
printf(" %d",ans[tem]);
}
printf("\n");
}
return 0;
}