题目链接:点这里!!!!
题意:有N个人排队,每一个人都有一个val来对应,每一个后来人都会插入当前队伍前面有pos个人。要求把队伍最后的状态输出。(N<=200000)
题解:
1、这道题我们按插入的顺序从后往前做就行,我们初始区间所有数都为1。
2、我们假设当前的位置为pos,是不是代表在当前插入以前有pos个数在其前面,我们相当于从后往前插入时,求前缀和为pos+1的位置在哪里?(看代码)
3、找到该位置之后再记录其的值,然后将该位置的值清零。再继续重复2的过程即可。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL long long #define pb push_back #define pa pair<int,int> #define clr(a,b) memset(a,b,sizeof(a)) #define lson lr<<1,l,mid #define rson lr<<1|1,mid+1,r #define bug(x) printf("%d++++++++++++++++++++%d\n",x,x) #define key_value ch[ch[root][1]][0]C:\Program Files\Git\bin const int MOD = 1E9+7; const LL N = 2E5+15; const int maxn = 1e4+1000; const int letter = 130; const int INF = 1e17; const double pi=acos(-1.0); const double eps=1e-8; using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n;///只要求输出终态 int sum[N<<2],ans[N]; struct node{ int val,pv,id; }a[N]; void pushup(int lr){ sum[lr]=sum[lr<<1]+sum[lr<<1|1]; } void build(int lr,int l,int r){ if(l==r){ sum[lr]=1; return; } int mid=(l+r)>>1; build(lson); build(rson); pushup(lr); } void update(int v,int lr,int l,int r){ if(l==r) { sum[lr]=0; return; } int mid=(l+r)>>1; if(v<=mid) update(v,lson); else update(v,rson); pushup(lr); } int query(int k,int lr,int l,int r){ if(l==r) return l; int mid=(l+r)>>1; if(sum[lr<<1]>=k) return query(k,lson); else return query(k-sum[lr<<1],rson); } int main(){ while(scanf("%d",&n)!=EOF){ build(1,1,n); for(int i=n;i>=1;i--){ scanf("%d%d",&a[i].pv,&a[i].val); } for(int i=1;i<=n;i++){ int p=query(a[i].pv+1,1,1,n); update(p,1,1,n); ans[p]=a[i].val; } for(int i=1;i<=n;i++) { if(i==1) printf("%d",ans[i]); else printf(" %d",ans[i]); } printf("\n"); } return 0; }