题目不再重述。
我也是看了解题报告的...之前怎么都想不到,如果正常模拟的话,每一次插入元素都必须准确的知道位置在pos的元素究竟是哪一个,知道连在那一个元素后面,才能正确的串成一个队嘛。。
如果用数组-- 向中间加元素要一个一个的挪
用链表--n^2 超时了。。
其他的数据结构?怎么都想不到一种可以动态维护记录每个元素(相对整个队列)绝对位置的 可insert 结构...
这时候就需要找规律了:加入0 1,0 2
后面来的2会把1挤掉,这是不是说后面的元素“更优先”一些呢?继续想下去,发现:最后一个元素插入的位置总是它最终的绝对位置!!
然后?--那倒数第二呢?它插入的位置似乎没啥规律,可是去掉已经固定位置的元素在看呢?
这时需要一个可以动态数出前面有几个空位的东西了--我用的是树状数组。
#include"stdio.h"
#include"stdlib.h"
#include"time.h"
#include"math.h"
#include"iostream"
#include"string.h"
#include"algorithm"
#include"vector"
#include"string"
#include"queue"
#include"map"
#define nmax 2001000
#define inf 0x7ffffff
#define eps 1e-8
#define PI 3.1415926535
#define PRIME 9999991
using namespace std;
int n;
int ans[nmax];
struct People{
int pi,vi;
int ti;
}peo[nmax];
//int pi[nmax],vi[nmax];
#define lowbit(x) (x)&(x^(x-1))
//int a[21];
int c[nmax];
void change(int k,int del)
{
while ( k<=n ) {
c[k]+=del;
k+=lowbit(k);
}
return ;
}
int get_num(int k)
{
int z=0;
while ( k>0 ) {
z+=c[k];
k-=lowbit(k);
}
return z;
}
int get_ans(int x,int y)
{
return get_num(y)-get_num(x-1);
}
int get_pos(int v){
///二分找到插入位置:
int mid,x=1,y=n+1;
while(x<y){
mid=x+(y-x)/2;
int front_num=mid-get_num(mid);
///how many 0 is in the front of mid;
if(front_num<=v){x=mid+1;}
//else if(front_num==v){break;}
else {y=mid;}
}
while(ans[x]!=-1)x++;
return x;
}
bool cmp(People a,People b){
if(a.pi==b.pi)return a.ti>b.ti;
return a.pi<b.pi;
}
int main(){
while(scanf("%d",&n)==1){
int i;
for(i=1;i<=n;i++){
//scanf("%d%d",&pi[i],&vi[i]);
//pi[i]++;
scanf("%d%d",&peo[i].pi,&peo[i].vi);
peo[i].pi++;
}
//io
//sort(peo,peo+n,cmp);
memset(ans,-1,sizeof(ans));
memset(c,0,sizeof(c));
for(i=n;i>0;i--){
int ipos=get_pos(peo[i].pi);
change(ipos,1);
ans[ipos]=peo[i].vi;
}
for(i=2;i<=n+1;i++){
printf("%d",ans[i]);
if(i!=n+1)putchar(' ');
}
puts("");
}
return 0;}