(第十四届蓝桥真题) 整数删除(线段树+二分)

 样例输入:

5 3
1 4 2 8 7

样例输出:

17 

分析:这道题我想的比较复杂,不过复杂度还是够用的,我是用线段树+二分来做的。

我们用线段树维护所有位置的最小值,那么我们每次删除一个数之前先求一遍最小值,不妨设最小值为mn,然后从左边开始找第一个值为mn的位置,不妨设位置为pos,我们每次删除一个数,就把这个位置设置为0x3f3f3f3f3f3f3f3f,因为可能爆int,所以设置为longlong里面的较大值。这样我们当前要删除pos位置的数,那么就把pos位置的数设置为0x3f3f3f3f3f3f3f3f,然后从pos-1向前二分寻找第一个位置i使得区间[i,pos-1]的最小值不为0x3f3f3f3f3f3f3f3f,这就是现存的左边相邻的数,同理从pos+1向后二分寻找第一个位置i使得区间[pos+1,i]的最小值不为0x3f3f3f3f3f3f3f3f,这就是现存的右边相邻的数,然后把这两个数都加上mn即可。

最后我们直接把那些位置不为0x3f3f3f3f3f3f3f3f的数输出即可。

细节见代码:

#include
#include
#include
#include
#include
using namespace std;
const int N=2e6+10;
long long mn[N];
int l[N],r[N];
void pushup(int id)
{
	mn[id]=min(mn[id<<1],mn[id<<1|1]);
	return ;
}
void build(int id,int L,int R)
{
	l[id]=L;r[id]=R;
	if(L==R)
	{
		scanf("%lld",&mn[id]);
		return ;
	}
	int mid=L+R>>1;
	build(id<<1,L,mid);
	build(id<<1|1,mid+1,R);
	pushup(id);
}
void update_point(int id,int pos,long long x)
{
	if(l[id]==r[id])
	{
		mn[id]+=x;
		return ;
	}
	int mid=l[id]+r[id]>>1;
	if(pos<=mid) update_point(id<<1,pos,x);
	else update_point(id<<1|1,pos,x);
	pushup(id);
}
long long query_interval(int id,int L,int R)
{
	if(l[id]>=L&&r[id]<=R) return mn[id];
	int mid=l[id]+r[id]>>1;
	long long ans=0x3f3f3f3f3f3f3f3f;
	if(L<=mid) ans=min(ans,query_interval(id<<1,L,R));
	if(mid+1<=R) ans=min(ans,query_interval(id<<1|1,L,R));
	return ans;
}
int main()
{
	int n,k;
	scanf("%d%d",&n,&k);
	build(1,1,n);
//	for(int i=1;i<=n;i++)
//	for(int j=i;j<=n;j++)
//	printf("%d %d %lld\n",i,j,query_interval(1,i,j));
	while(k--)
	{
		long long mi=query_interval(1,1,n);
		int l=1,r=n;
		while(l>1;
			if(query_interval(1,1,mid)<=mi) r=mid;
			else l=mid+1;
		}
		long long val=query_interval(1,l,l);
//		printf("%lld\n",val);
		update_point(1,l,0x3f3f3f3f3f3f3f3f-val);
//		if(query_interval(1,l,l)==0x3f3f3f3f3f3f3f3f) puts("11111111111");
		int t=l;
		if(t!=1)//更新左边 
		{
			l=1,r=t-1;
			while(l>1;
				if(query_interval(1,mid,t-1)!=0x3f3f3f3f3f3f3f3f) l=mid;
				else r=mid-1;
			}
			if(query_interval(1,l,t-1)!=0x3f3f3f3f3f3f3f3f)
			{
//				printf("%d\n",l);
				update_point(1,l,val);
			}
		}
		if(t!=n)//更新右边 
		{
			l=t+1,r=n;
			while(l>1;
				if(query_interval(1,t+1,mid)!=0x3f3f3f3f3f3f3f3f) r=mid;
				else l=mid+1;
			}
			if(query_interval(1,t+1,l)!=0x3f3f3f3f3f3f3f3f)
			{
//				printf("%d\n",l);
				update_point(1,l,val);
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		long long val=query_interval(1,i,i);
		if(val!=0x3f3f3f3f3f3f3f3f) printf("%lld ",val);
	}
	return 0;
}

你可能感兴趣的:(蓝桥杯,职场和发展)