[ZJOI2020] Sequence-Greedy + Planning

Title description

[ZJOI2020] Sequence

answer

The title adds a skipping operation on the basis of the continuous deletion operation, which is equivalent to that you can cover each point with several straight lines and jumpers, and each point is required to be covered exactly a[i] times

Greedy consider the simplest case, only two points 1, 2:

  1. a1>0, a2>0, connect min(a1,a2) straight lines from 1 to the back;
  2. a1>0, a2=0, connect a1 jumpers from 1 to the back;
  3. a1=0, a2>0, do not handle it temporarily.

Sweep down in this way, when the i-th point is reached, assuming that z straight lines and b valid jumpers are connected,

If z+b≤ai, then z+b must be subtracted directly;

If z+b>ai, it means that there are z+b-ai lines to be cut, then cut straight or jumper? Many people will get stuck here, thinking that they must cut the jumper first and keep the straight line (I thought so at the beginning), but they can't pass the big example, see this for details:

4 1 3 0 3 0 3

When scanning to the first 3, there is 1 straight line and 3 jumpers, obviously keep the jumpers;

So we found that whether to keep a straight line or a jumper depends on the following points, so we can make a mark: set k=z+b-ai, subtract k from both z and b, and then give this point k free straight lines or jumps Therefore, when making a decision at this point, it can be assumed that the k lines have been determined, then ai is just reduced to 0, and then two points are greedy with a(i-1),

Then how to deal with the mark, we can add ai to k, and then subtract k from ans, because the added k must be subtracted k times at the end, that is, the k lines will be counted as k contributions. Omit it in the answer;

The algorithm is basically complete here, but there is still a problem: z and b cannot be reduced to negative numbers

Think about it if z<k, that is, z<z+b-ai, b>ai, only the ai line can be reserved, then the jumper must be cut off b-ai, then k'=z+ai-ai= z, z will not be reduced to negative;

The same is true for b<k.

Code

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<queue>
#define ll long long
#define MAXN 100005
#define mod 998244353ll
using namespace std;
inline ll read(){
	ll x=0,f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f*=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+s-'0';s=getchar();}
	return f>0?x:-x;
}
int T=read(),n,m,p;
ll a[MAXN];
int main()
{
	while(T--){
		n=read(),m=n+1>>1;
		for(int i=1;i<=n;i++)a[i]=read();
		ll z=0,b=0,c=0,ans=0;a[n+1]=0;
		for(int i=2;i<=n+1;i++){
			ll d=0;
			if(a[i]<z+b){
				ll k=z+b-a[i];
				if(k>z)b-=k-z,k=z;
				if(k>b)z-=k-b,k=b;
				z-=k,b-=k,a[i]-=k,d=k;
			}a[i]-=z+b;
			ll mn=min(a[i],a[i-1]);
			a[i-1]-=mn,a[i]-=mn,ans+=mn,z+=mn;
			ans+=a[i-1],c+=a[i-1],a[i-1]=0;
			a[i]+=d,ans-=d,swap(b,c);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

 

Guess you like

Origin blog.csdn.net/weixin_43960287/article/details/109274146