Codeforces Round #636 (Div. 3)D. Constant Palindrome Sum(差分 or 线段树)

D. Constant Palindrome Sum

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given an array aa consisting of nn integers (it is guaranteed that nn is even, i.e. divisible by 22). All aiai does not exceed some integer kk.

Your task is to replace the minimum number of elements (replacement is the following operation: choose some index ii from 11 to nn and replace aiai with some integer in range [1;k][1;k]) to satisfy the following conditions:

  • after all replacements, all aiai are positive integers not greater than kk;
  • for all ii from 11 to n2n2 the following equation is true: ai+an−i+1=xai+an−i+1=x, where xx should be the same for all n2n2 pairs of elements.

You have to answer tt independent test cases.

Input

The first line of the input contains one integer tt (1≤t≤1041≤t≤104) — the number of test cases. Then tt test cases follow.

The first line of the test case contains two integers nn and kk (2≤n≤2⋅105,1≤k≤2⋅1052≤n≤2⋅105,1≤k≤2⋅105) — the length of aa and the maximum possible value of some aiai correspondingly. It is guratanteed that nn is even (i.e. divisible by 22). The second line of the test case contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤k1≤ai≤k), where aiai is the ii-th element of aa.

It is guaranteed that the sum of nn (as well as the sum of kk) over all test cases does not exceed 2⋅1052⋅105 (∑n≤2⋅105∑n≤2⋅105, ∑k≤2⋅105∑k≤2⋅105).

Output

For each test case, print the answer — the minimum number of elements you have to replace in aa to satisfy the conditions from the problem statement.

Example

input

Copy

4
4 2
1 2 1 2
4 3
1 2 2 1
8 7
6 1 1 7 6 3 4 6
6 6
5 2 6 1 3 4

output

Copy

0
1
4
2

题意:

给出n个数字,跟一个k,你可以把a[i]变成任何不大于k的数字,但是需要一个代价。

现在问你使得所有的a[i] + a[n - i + 1] = 某个数字x的最小代价,x是你自己定的。

思路:

一开始想的贪心,写完发现样例没过。。发现因为变的数字有范围,所以这个x是不太好确定的,但是

这个k只有2e5,那么这个x定的范围也就是2~4e5,那么我们可以计算一下对于每个i使得a[i] + a[n - i + 1]

变成这些数字的代价,最后再遍历得到最优的解。线段树跟差分都可以写,代码有注释应该比较清楚。

差分:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 4e5 + 40;
int a[N];
int d[N];
int c[N];
void add(int L, int R, int val)
{
    if (L > R)
        return ;
    c[L] += val;
    c[R + 1] -= val;
}
int main()
{
#ifdef LOCAL
	freopen("E:/input.txt", "r", stdin);
#endif
    int t;
    cin >> t;
    while (t--)
    {
        int n, k;
        cin >> n >> k;
        memset(c, 0, sizeof c[0] * (2 * k + 10));
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        for (int i = 1; i <= n / 2; i++)
        {
            int mi = min(a[i], a[n - i + 1]);
            int mx = max(a[i], a[n - i + 1]);
            add(mi + 1, mx + k, 1); //将这两个数字的和变成这个区间的数字,只需要改变mi
            add(mx + k + 1, 2 * k, 2); // 变成这两个区间,肯定两个数字都要变
            add(mi + mx, mi + mx, -1);  // 当前这个数字不用变化即可以得到,那么去掉一个代价,因为之前加了
            add(1, mi, 2); //两个数字都需要变成小于mi的,代价为2
        }
        int ans = 0x3f3f3f3f;
        for (int i = 1; i <= 2 * k; i++)
            d[i] = d[i - 1] + c[i], ans = min(ans, d[i]);
        cout << ans << endl;
    }
	return 0;
}

线段树:

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mod = 10000;
const int N = 4e5 + 10;
int a[N];
ll c[N * 4];
ll lzy[N * 4];
#define ls ((x) << 1)
#define rs ((x) << 1 | 1)
#define mid ((L) + (R) >> 1)
void Modify(ll x, ll L, ll R, ll val)
{
	c[x] += val;
	lzy[x] += val;
}
void push_up(int x)
{
	c[x] = min(c[ls], c[rs]);
}
void push_down(int x, int L, int R)
{
	if (lzy[x])
	{
		Modify(ls, L, mid, lzy[x]);
		Modify(rs, mid + 1, R, lzy[x]);
		lzy[x] = 0;
	}
}
void build(int x, int L, int R)
{
	lzy[x] = c[x] = 0;
	if (L == R)
	{
		return;
	}
	build(ls, L, mid);
	build(rs, mid + 1, R);
	push_up(x);
}
void update(int x, int L, int R, int ql, int qr, int val)
{
        if(ql > qr)
            return;
	if (ql <= L && qr >= R)
	{
		c[x] += val;
		lzy[x] += val;
		return;
	}
	push_down(x, L, R);
	if (ql <= mid)
		update(ls, L, mid, ql, qr, val);
	if (qr > mid)
		update(rs, mid + 1, R, ql, qr, val);
	push_up(x);
}
int main()
{
#ifdef LOCAL
	freopen("E:/input.txt", "r", stdin);
#endif
	int t;
	cin >> t;
	while (t--)
	{
		ll n, k;
		cin >> n >> k;
		build(1, 1, 2 * k);
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i]);
		for (int i = 1; i <= n / 2; i++)
		{
			int mi = min(a[i], a[n - i + 1]);
			int mx = max(a[i], a[n - i + 1]);
			update(1, 1, 2 * k, mi + 1, mx + k, 1);
			update(1, 1, 2 * k, mx + k + 1, 2 * k, 2);
			if (mi + mx <= mx + k)
				update(1, 1, 2 * k, mi + mx, mi + mx, -1);
			update(1, 1, 2 * k, 1, mi, 2);
		}
		cout << c[1] << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43731933/article/details/105687967