codeforces1406D Three Sequences

https://codeforces.com/contest/1406/problem/D

菜到爆炸,1个小时20分钟没想出来怎么求这个值

这题就是要求min{max(bn,c1)},然后发现ai和ai-1之间的大小关系可以限制bi,bi-1,ci,ci-1的大小。。。

假设a1=b1+c1, b1=a1-mx,c1=mx

那么由于b1<=b2,c1>=c2

得b2>=a1-mx,b2>=a2-mx ,我们希望b序列递增的尽可能慢来让最后bn尽可能小,所以会取max(a1-mx,a2-mx)

那么a1>=a2时,b1=b2=a1-mx,但是a1<a2时,b2=a2-mx,b1+a2-a1=b2,

设所有相邻差值大于0的差值之和为K,那么bn=a1+K-mx   ,而bn本身也就是mx,那么最小值就是2mx=a1+K了

修改操作就只要考虑一下l,l-1和r+1,r的差值即可

用树状数组维护一下每个点的值就行

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=3e5+10;

int n,m,cnt,tot,cas;ll ans;
ll now;
ll a[maxl];
ll b[maxl];
bool vis[maxl];
char s[maxl];

inline void prework()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	now=0;
	for(int i=2;i<=n;i++)
	if(a[i-1]<a[i])
		now+=a[i]-a[i-1];
}

inline ll sum(int i)
{
	ll ret=0;
	while(i)
	{
		ret+=b[i];
		i-=i&-i;
	}
	return ret;
}

inline void add(int i,int x)
{
	while(i<=n+1)
	{
		b[i]+=x;
		i+=i&-i;
	}
}

inline void mainwork()
{
	scanf("%d",&m);
	if(a[1]+sum(1)+now>=0)
		ans=(a[1]+sum(1)+now+1)/2;
	else
		ans=(a[1]+sum(1)+now)/2;
	printf("%lld\n",ans);
	int l,r,x;ll d;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&l,&r,&x);
		if(l>1)
		{
			d=a[l]+sum(l)-a[l-1]-sum(l-1);
			if(d>0)
				now-=d;
		}
		if(r<n)
		{
			d=a[r+1]+sum(r+1)-a[r]-sum(r);
			if(d>0)
				now-=d;
		}
		add(l,x);
		add(r+1,-x);
		if(l>1)
		{
			d=a[l]+sum(l)-a[l-1]-sum(l-1);
			if(d>0)
				now+=d;
		}
		if(r<n)
		{
			d=a[r+1]+sum(r+1)-a[r]-sum(r);
			if(d>0)
				now+=d;
		}
		if(a[1]+sum(1)+now>=0)
			ans=(a[1]+sum(1)+now+1)/2;
		else
			ans=(a[1]+sum(1)+now)/2;
		printf("%lld\n",ans);
	}
}

int main()
{
	int t=1;
	//scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/108588304