CF-div3-636-D. Constant Palindrome| 静态区间修改 差分 贪心 分类讨论

思路

考虑最终修改后和为x,x的值到底是多少最优。

作分类讨论:

1.x在[2,mi] 一定要改两次 因为把把ai和an-i+1中最大的数改成1 也比x大; 所以把[2,mi]修改次数+2
2.x在[mx+k+1,2k] 一定要改两次 因为把ai和an-i+1中最大的数加k也到不了x;所以把[mx+k+1,2k]修改次数+2
3.x在[mi+1,mx+k] 且不等于 sum 可贪心只改一次就能该到x;所以把[mi+1,mx+k]修改次数+1

因为是静态区间修改,所以用差分数组即可,用线段树区间修改也行。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4e5+100;
ll a[maxn],delta[maxn];
int t;
int n,k;

void solve(){
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=2*k+10;i++) delta[i] = 0;
	for(int i=1;i<=n;i++){
		if(i <= n/2){
			ll sum = a[i] + a[n-i+1];
			ll mx = max(a[i],a[n-i+1]);
			ll mi = min(a[i],a[n-i+1]);
			//1.x在[2,mi] 一定要改两次 因为把最大的改成1 也比x大 
			delta[2]+=2;
			delta[mi+1]-=2;
			//2.x在[mx+k+1,2*k] 一定要改两次 因为把最大的加k也到不了x 
			delta[mx+k+1]+=2;
			delta[2*k+1]-=2;
			//3.x在[mi+1,mx+k] 且不等于 sum 可贪心只改一次
			delta[mi+1]++;
			delta[mx+k+1]--;
			delta[sum]--;
			delta[sum+1]++;
		}
	}
	ll ans = delta[2];
	for(int i = 2;i<=2*k;i++){
		delta[i] += delta[i-1]; 
		ans = min(ans,delta[i]);
	}
	cout<<ans<<endl;
}

int main(){
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
} 
posted @ 2020-04-22 22:08  fishers  阅读(185)  评论(0编辑  收藏  举报