首先让我们感谢昨天BestCoder的出题人Claris,以及各位Hacker,让我这个帮老妈刷票刷了半个小时结果,19:40多才开始打得水笔A了3道题,本来只有rank30左右的,结果硬生生地被hack到了rank10,结果rating还是只涨了100多(话说我某次rank30多也是涨100多啊),下一场还是不能打DIV1,不过没关系,反正DIV2都AK不了还做毛DIV1啊。
然后呢,继续填坑。
今天突然发现了一个黑科技。
没错就是这道题。
题意的话很简单啊,序列插入操作。
来来来Splay走起来~~~~~~~~~~~~~~~~~~~~~~~~~~~
????????????
TLE!!!!
出题人你几个意思啊,Splay你都卡。
然后发现线段树好像可做。
从后往前插入,每次找到第pos+1个空位,然后在这里插,把这个空位删掉。
嗯就这么结束了。
当然不!
众所周知某一部分线段树能完成的操作树状数组也可以完成。
只要满足区间减法就行了(Jxr:树状数组这么短,就像我一样(嘿嘿嘿))
于是我们可以二分+BIT,两个log。
但是这不合理啊,树状数组这么短的东西怎么可以这么慢呢。
于是我闲得无聊逛评论区,结果发现了黑科技。
BIT的sumseek(k)操作。
找到前缀和>=k的第一个位置。
具体见代码。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=200000+5;
int d[N],v[N],n;
int lowbit(int x){
return x&-x;
}
int sumseek(int k){
int ans=0,sum=0;
for(int i=18;i>=0;i--){
ans+=(1<<i);
if(ans>=n||sum+d[ans]>=k)ans-=(1<<i);
else sum+=d[ans];
}
return ans+1;
}
void add(int x,int v){
for(;x<=n;x+=lowbit(x))d[x]+=v;
}
int pos[N],val[N];
int main(){
//freopen("a.in","r",stdin);
while(scanf("%d",&n)==1){
for(int i=1;i<=n;i++)add(i,1);
for(int i=1;i<=n;i++)scanf("%d%d",&pos[i],&val[i]);
for(int i=n;i>=1;i--){
int k=sumseek(pos[i]+1);
v[k]=val[i];
add(k,-1);
}
for(int i=1;i<=n;i++)
printf("%d ",v[i]);
putchar('\n');
}
return 0;
}