http://poj.org/problem?id=2828
坑爹呀你
c++ 跑不到2000
g++ 直接超时
有这么夸张吗 无语了
题目大意:
买票 不过有插队的 n个人依次插队
给你插队位置和value 问你最后value顺序
其实就是最后人的顺序
这题最好倒着插入因为 最后一个人如果插在第m个空的后面 那么他一定在m+1的位置
倒着来的话 无路第几个人 他插在第m个空的后面 那么他的左面就需要m个空位
在这里线段树只不过用来二分搜索
代码及其注释:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<queue> #include<algorithm> #include<vector> using namespace std; const int N=200005; struct node { int empsum; int l,r; }mem[N*4]; int pos[N]; int value[N]; int ans[N]; int n; void build(int x,int l,int r) { mem[x].l=l; mem[x].r=r; mem[x].empsum=(r-l+1);//初始这段空间的空格数 if(l==r) return; int mid=(l+r)>>1; build(x*2,l,mid); build(x*2+1,mid+1,r); } void insert(int x,int i) { --mem[x].empsum;//所到区间空位均减一 if(mem[x].l==mem[x].r) { ans[mem[x].l]=value[i];//如果到了叶子节点 说明value的位置已找到 } else { if(mem[x*2].empsum>pos[i])//如果左面有足够的空位则向左搜 { insert(x*2,i); } else { pos[i]-=mem[x*2].empsum;//否则向右搜 不过在右面的话 所需空位置减少了左面的空位数 insert(x*2+1,i); } } } int main() { while(scanf("%d",&n)!=EOF) { build(1,1,n); for(int i=1;i<=n;++i) { scanf("%d %d",&pos[i],&value[i]); } for(int i=n;i>=1;--i) { insert(1,i); } for(int i=1;i<=n;++i) { if(i>1) printf(" "); printf("%d",ans[i]); } printf("\n"); } return 0; }