回文数组 | 第十五届蓝桥杯省赛C++C组

小蓝在无聊时随机生成了一个长度为 nn 的整数数组,数组中的第 ii 个数为 aiai,他觉得随机生成的数组不太美观,想把它变成回文数组,也是就对于任意 i∈[1,n]i∈[1,n] 满足 ai=an−i+1ai=an−i+1。

小蓝一次操作可以指定相邻的两个数,将它们一起加 11 或减 11;也可以只指定一个数加 11 或减 11,请问他最少需要操作多少次能把这个数组变成回文数组?

输入格式

输入的第一行包含一个正整数 nn。

第二行包含 nn 个整数 a1,a2,…,ana1,a2,…,an,相邻整数之间使用一个空格分隔。

输出格式

输出一行包含一个整数表示答案。

数据范围

对于 20%20% 的评测用例,1≤n≤101≤n≤10。
对于所有评测用例,1≤n≤1051≤n≤105,−106≤ai≤106−106≤ai≤106。

输入样例:
4
1 2 3 4
输出样例:
3
样例解释

第一次操作将 a1,a2a1,a2 加 11,变为 2,3,3,42,3,3,4;

后面两次操作将 a1a1 加 11,变为 4,3,3,44,3,3,4。

题解:

        没有tag提示呜呜呜,看题目其实感觉像是动态规划来着,感觉看什么都像动态规划。

        实际是贪心写的,遍历一半的数组,能同时两个操作就两个,不能就单独操作一个即可,比较简单的算法。

代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;

int n=0;
vector<int> vt(100005,0);
long long int cnt=0;

int main(){
    cin >> n;
    for(int i=0;i<n;i++){
        cin >> vt[i];
    }
    long long int t=0;
    for(int i=0;i<n/2;i++){
        if(vt[i]==vt[n-i-1]){
            continue;
        }
        int t1=i;int t2=n-i-1;
        if(vt[t1]<vt[t2] && vt[t1+1]<vt[t2-1]){
            t=min(vt[t2]-vt[t1],vt[t2-1]-vt[t1+1]);
            vt[t1]+=t;vt[t1+1]+=t;
            cnt+=t;i--;
        }
        else if(vt[t1]>vt[t2] && vt[t1+1]>vt[t2-1]){
            t=min(vt[t1]-vt[t2],vt[t1+1]-vt[t2-1]);
            vt[t1]-=t;vt[t1+1]-=t;
            cnt+=t;i--;
        }
        else{
            if(vt[i]<vt[n-i-1]){
                t=vt[n-i-1]-vt[i];
                vt[i]+=t;
                cnt+=t;
            }
            else if(vt[i]>vt[n-i-1]){
                t=vt[i]-vt[n-i-1];
                vt[i]-=t;
                cnt+=t;
            }
            i--;
        }
    }
    cout << cnt <<"\n";
}