题意:给定十万个数a[ m ],然后有十万个操作,每次给现有序列加一个字符(0或1),或者删掉已有序列中,第 a[0] 个,第a[1]个,...,第a[m]个。
序列最多有10万个1或0. 删除操作最多进行10万次。
于是用线段树来储存。每个节点,存这个点还剩下多少个点没有删除,这样就可以删除指定的第k 个数。
给序列加元素最多进行n次,每次复杂度 O(log2(n)) ,最多 O(n*log2(n));
删除元素最多进行 n 次,每次复杂度 O(log2(n)) ,最多 O(n*log2(n));
所以总复杂度O(n*log2(n));
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define maxn 1000010
using namespace std;
int N,n,m,Now,op;
int a[maxn];
int index[maxn<<2];
int value[maxn];
void ST_Init(){
N=1;while(N <n+2) N <<=1;
memset(index,0,sizeof(index));
}
void PushUp(int rt){
index[rt]=index[rt<<1]+index[rt<<1|1];
}
void Set(int X,int C,int l,int r,int rt){//将X位置设置为C
if(l==r){
value[l]=C;
index[rt]=1;
++Now;
return;
}
int m=(l+r)>>1;
if(X <=m) Set(X,C,l,m,rt<<1);
else Set(X,C,m+1,r,rt<<1|1);
PushUp(rt);
}
void Del(int X,int l,int r,int rt){//删除第X个元素
if(l==r){
index[rt]=0;
return;
}
int m=(l+r)>>1;
if(X <= index[rt<<1]) Del(X,l,m,rt<<1);
else Del(X-index[rt<<1],m+1,r,rt<<1|1);
PushUp(rt);
}
void show(){//显示
for(int i=0;i<Now;++i){
if(index[N+i]){
printf("%d",value[i+1]);
}
}
cout<<endl;
}
int main(void)
{
while(~scanf("%d%d",&n,&m)){
Now=1;ST_Init();
for(int i=0;i<m;++i) scanf("%d",&a[i]);
for(int i=0;i<n;++i) {
scanf("%d",&op);
if(~op){
Set(Now,op,1,N,1);
}
else{
for(int j=0;j<m&&a[j]-j<=index[1];j++){//<span style="font-family: Arial, Helvetica, sans-serif;">注意,这里是删掉第a[ j ]</span><span style="font-family: Arial, Helvetica, sans-serif;">个元素,</span>
Del(a[j]-j,1,N,1);//因为已经删掉了j个元素了,本次操作前的第a[j]个是现在的第 <span style="font-family: Arial, Helvetica, sans-serif;">a[ j ] - j 个</span><span style="font-family: Arial, Helvetica, sans-serif;">。</span>
}
}
}
if(index[1]){
show();
}
else{
printf("Poor stack!\n");
}
}
return 0;
}