C2-Pokémon Army (hard version) (thinking + difference / line segment tree + dp) detailed explanation

https://codeforces.com/contest/1420/problem/C2


This question exercises thinking very much, and it also made me know that it is also a difference. Subtracting the back from the front and subtracting the front from the back have different meanings.

Remember c1? We are looking for the peaks and valleys. In fact, if you use the idea of ​​difference to find the peaks and valleys, you can make the c2 problem. What do you mean?

The difference between the peaks and troughs must be the sum of the difference between the intermediate values, so the peaks and troughs can be seen as whether the difference can be done.

For example, 1 2 5 4 3 6 7, the difference from front to back is -1,-3,1,2,-3,-1,7. You will find such a thing. Adding all the differences of the positive numbers is the final value of the peaks and troughs obtained at the end.

For example, 5 4 3 finds 5 3 (in the example above), the difference found is actually (5-4) + (4-3)

The minimum value found is the monotonicity of the peaks and troughs. Then the difference between the two values ​​is the answer.

If you draw a simulated line in Figure 5-4-3, you can find that the middle point has almost no effect, in fact it is the difference between these values.

Then, after discovering this, the following operation is equivalent to changing the position of the two numbers in the array, and performing such a similar operation again.

Before the exchange, consider whether the front and back of l are positive numbers, subtract them if they are, and whether the front and back of r are positive numbers, and subtract them if they are. Note that the case of l==r-1 is specially judged to prevent more additions and more subtractions. Just include one situation in it.

After the exchange, see if any adjacent difference is positive, and add the positive one. Then output. swap is just fine.

Enlightenment: To find the peaks and valleys, you can go to the back difference to think.

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=3e5+100;
typedef long long LL;
LL a[maxn];
void solve()
{
	LL n,q;cin>>n>>q;
	LL res=0;
	for(LL i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	for(LL i=1;i<=n;i++){
		if(a[i]-a[i+1]>0) res+=(a[i]-a[i+1]);
	}
	cout<<res<<endl;
	while(q--)
	{
		LL l,r;cin>>l>>r;
		if(a[l-1]-a[l]>0) res-=(a[l-1]-a[l]);
		if(a[r-1]-a[r]>0&&l!=r-1) res-=(a[r-1]-a[r]);
		if(a[l]-a[l+1]>0) res-=(a[l]-a[l+1]);
		if(a[r]-a[r+1]>0) res-=(a[r]-a[r+1]);
		
		swap(a[l],a[r]);
		if(a[l-1]-a[l]>0) res+=(a[l-1]-a[l]);
		if(a[r-1]-a[r]>0&&l!=r-1) res+=(a[r-1]-a[r]);
		if(a[l]-a[l+1]>0) res+=(a[l]-a[l+1]);
		if(a[r]-a[r+1]>0) res+=(a[r]-a[r+1]);
		cout<<res<<endl;
	}
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL t;cin>>t;
  while(t--)
  {
  	memset(a,0,sizeof(a)); 
  	solve();
  }
return 0; 
}
 

Finally, add the dp of the line segment tree. I saw someone submit this. But I can't understand this transfer.

This constant is pretty big.//It's ugly, it will be TLE.

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
#define INF 1e18;
using namespace std;
const int maxn=3e5+100;
typedef long long LL;
int n,q;
int a[maxn];
struct Node{
	LL v[2][2];
	Node(){
		v[0][0]=v[1][1]=v[0][1]=v[1][0]=-INF;
	}
	Node(LL x){
		v[0][0]=x;
		v[1][1]=-x;
		v[0][1]=v[1][0]=-INF;
	}
	Node operator+(Node &p){
		Node ret;
		for(int i=0;i<2;i++){
			for(int j=0;j<2;j++)
			{
				ret.v[i][j]=max({v[i][j],p.v[i][j],v[i][0]+p.v[1][j],v[i][1]+p.v[0][j]});
			}
		}
		return ret;
	}
}tree[maxn*4];
void update(int p,int l,int r,int i,int x)
{
	if(l==r){
		tree[p]=Node(x);return;
	}
	int mid=(l+r)>>1;
	if(i<=mid) update(p*2,l,mid,i,x);
	if(i>mid) update(p*2+1,mid+1,r,i,x);
	tree[p]=tree[p*2]+tree[p*2+1];
}
int main(void)
{
  //cin.tie(0);std::ios::sync_with_stdio(false);
  int t;scanf("%d",&t);
  while(t--)
  {
  	scanf("%d%d",&n,&q);
  //	for(LL i=0;i<=n+10;i++) a[i]=0,update(1,1,n,i,a[i]); 
	for(int i=1;i<=n;i++) cin>>a[i],update(1,1,n,i,a[i]);
  	printf("%lld\n",tree[1].v[0][0]);
  	while(q--)
  	{
  		int l,r;scanf("%d%d",&l,&r);
  		swap(a[l],a[r]);
  		update(1,1,n,l,a[l]);
  		update(1,1,n,r,a[r]);
  		printf("%lld\n",tree[1].v[0][0]);
  	}
  }
return 0;
}
 

 

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/108819446