Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 13823 | Accepted: 5626 |
Description
N Transaction i Black Box contents after transaction Answer
(elements are arranged by non-descending)
1 ADD(3) 0 3
2 GET 1 3 3
3 ADD(1) 1 1, 3
4 GET 2 1, 3 3
5 ADD(-4) 2 -4, 1, 3
6 ADD(2) 2 -4, 1, 2, 3
7 ADD(8) 2 -4, 1, 2, 3, 8
8 ADD(-1000) 2 -1000, -4, 1, 2, 3, 8
9 GET 3 -1000, -4, 1, 2, 3, 8 1
10 GET 4 -1000, -4, 1, 2, 3, 8 2
11 ADD(2) 4 -1000, -4, 1, 2, 2, 3, 8
Input
Output
Sample Input
7 4
3 1 -4 2 8 -1000 2
1 2 6 6
Sample Output
3
3
1
2
Source
有一些ADD和GET操作。n次ADD操作,每次往序列中加入一个数,由ADD操作可知序列长度为1-n时序列的组成。GET操作输入一个序列长度,第i个数 ai 表示你需要输出当前长度序列为 ai (即在第 ai 次ADD操作后)第i大的元素的值。给出的GET操作输入非降。
虽然这题好像一眼望上去就是splay,或者一些STL的奇技淫巧过这题,但我太菜了并不会splay这个东西,所以我就用上了不久前刚学到的替罪羊树,没想到还跑得挺快,在POJ上只用了94ms,因为这只是一道模板题,所以……好像也没什么好讲的..只是我刚开始记录下查询操作的时候用的是map里套vector来表示在这个ADD操作后是否有查询值,结果T掉了..然后我发现GET操作输入的序列是非降的。。于是只要在操作的时候记录上次已经查询完的位置在哪然后直接在那里往下找就行了。
#pragma GCC optimize(3)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
struct ScapeGoatTree {
static const int maxn=200010,oo=(1LL<<31)-1;
static const double alpha=0.75;
int cntx,root;
struct TreeNode {
int son[2];
int fa;
int siz;
int num;
}t[maxn];
int treeid[maxn],cnt;
inline bool balance(int id) {
return (double)t[id].siz*alpha>=(double)t[t[id].son[0]].siz&&(double)t[id].siz*alpha>=(double)t[t[id].son[1]].siz;
}
inline void recycle(int id) {
if(t[id].son[0])
recycle(t[id].son[0]);
treeid[++cnt]=id;
if(t[id].son[1])
recycle(t[id].son[1]);
}
inline int build(int l,int r) {
if(l>r)
return 0;
int mid=(l+r)>>1,id=treeid[mid];
t[t[id].son[0]=build(l,mid-1)].fa=id;
t[t[id].son[1]=build(mid+1,r)].fa=id;
t[id].siz=t[t[id].son[0]].siz+t[t[id].son[1]].siz+1;
return id;
}
inline void rebuild(int id) {
cnt=0;
recycle(id);
int fa=t[id].fa,child=t[t[id].fa].son[1]==id,current=build(1,cnt);
t[t[fa].son[child]=current].fa=fa;
if(id==root)
root=current;
}
inline void insert(int x) {
int now=root,current=++cntx;
t[current].siz=1;t[current].num=x;
while(1) {
t[now].siz++;
bool child=x>=t[now].num;
if(t[now].son[child])
now=t[now].son[child];
else {
t[t[now].son[child]=current].fa=now;
break;
}
}
int need=0;
for(int i=current;i;i=t[i].fa)
if(!balance(i))
need=i;
if(need)
rebuild(need);
}
inline int get_kth(int x) {
int now=root;
while(1) {
if(t[t[now].son[0]].siz==x-1)
return now;
else if(t[t[now].son[0]].siz>=x)
now=t[now].son[0];
else {
x-=t[t[now].son[0]].siz+1;
now=t[now].son[1];
}
}
return now;
}
inline void init() {
cntx=2;root=1;
t[1].num=-oo,t[1].siz=2,t[1].son[1]=2;
t[2].num=oo,t[2].siz=1,t[2].fa=1;
}
int n,q,val[300001],pos,o[300001];
inline void main() {
init();
read(n);read(q);
for(int i=1;i<=n;i++)
read(val[i]);
for(int i=1;i<=q;i++)
read(o[i]);
int pos=1;
for(int i=1;i<=n;i++) {
insert(val[i]);
while(o[pos]==i)
writeln(t[get_kth(pos+1)].num),pos++;
}
}
}SGT;
int main() {
SGT.main();
return 0;
}