CodeForces 374 D. Inna and Sequence

题意:给定十万个数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;
}













你可能感兴趣的:(CodeForces 374 D. Inna and Sequence)