题意就是 给出一段插入,求出最后的序列。
做到n*logn基本都能过。
我用线段树做的。不过开始没想到怎么解决插入顺序问题,只知道存一个数组表示当前可以插入几个数。
后来ACdream群给了解答。每次update的时候,如果left的插入数大于插入就继续,否者就走right,并且将插入改为插入-left的插入数。
//PS 其实,觉得SBT应该能做的。
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<stack> #include<iostream> #include<list> #include<set> #include<bitset> #include<vector> #include<cmath> #define INF 0x7fffffff #define eps 1e-8 #define LL long long #define PI 3.141592654 #define CLR(a,b) memset(a,b,sizeof(a)) #define FOR(i,a,b) for(int i=a;i<b;i++) #define FOR_(i,a,b) for(int i=a;i>=b;i--) #define pub push_back #define puf push_front #define pob pop_back #define pof pop_front #define mp make_pair #define ft first #define sd second #define sf scanf #define pf printf #define sz(v) ((int)(v).size()) #define all(v) (v).begin(),(v).end() #define acfun std::ios::sync_with_stdio(false) #define SIZE (200000+1) #define MOD 1000000007 using namespace std; struct node { int pos; int val; } l[SIZE]; int s[SIZE*3]; int res[SIZE]; void build(int l,int r,int o) { if(l==r) s[o]=1; else { int m=(l+r)>>1; build(l,m,o*2); build(m+1,r,o*2+1); s[o]=s[o*2]+s[o*2+1]; } } void update(int l,int r,int o,int us,int up) { s[o]--; if(l==r) res[l]=up; else { int m=(l+r)>>1; if(s[o*2]>=us) update(l,m,o*2,us,up); else update(m+1,r,o*2+1,us-s[o*2],up); } } int main() { int n; while(~sf("%d",&n)) { build(1,n,1); FOR(i,0,n) { sf("%d%d",&l[i].pos,&l[i].val); l[i].pos++; } FOR_(i,n-1,0) { update(1,n,1,l[i].pos,l[i].val); } FOR(i,1,n) pf("%d ",res[i]); pf("%d\n",res[n]); } }
原文地址:http://blog.csdn.net/dongshimou/article/details/43150751