CodeForces - 501E Misha and Palindrome Degree

E. Misha and Palindrome Degree
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Misha has an array of n integers indexed by integers from 1 to n. Let's define palindrome degree of array a as the number of such index pairs (l, r)(1 ≤ l ≤ r ≤ n), that the elements from the l-th to the r-th one inclusive can be rearranged in such a way that the whole array will be a palindrome. In other words, pair (l, r) should meet the condition that after some rearranging of numbers on positions from l to r, inclusive (it is allowed not to rearrange the numbers at all), for any 1 ≤ i ≤ n following condition holds: a[i] = a[n - i + 1].

Your task is to find the palindrome degree of Misha's array.

Input

The first line contains integer n (1 ≤ n ≤ 105).

The second line contains n positive integers a[i] (1 ≤ a[i] ≤ n), separated by spaces — the elements of Misha's array.

Output

In a single line print the answer to the problem.

Examples
input
Copy
3
2 2 2
output
Copy
6
input
Copy
6
3 6 5 3 3 5
output
Copy
0
input
Copy
5
5 5 2 5 2
output
Copy
4
Note

In the first sample test any possible pair (l, r) meets the condition.

In the third sample test following pairs (1, 3), (1, 4), (1, 5), (2, 5) meet the condition.

传送门链接

题意:给n个不超过n的数,取其中一段区间进行重新排列,使之成为回文串,求有多少种方案数?

分析:开始想啦很久没思路,然后手推啦几组找到啦一些规律。即首先找到一个最小的区间,重排就能使数组变成回文串。先从两端开始向中间找最大的回文串。然后中间的串是一个第一个字符和最后一个字符不相等的。这个时候,以这个中间的字符串的首尾字符开始寻找最小的重排区间。然后就能用计数乘法法则得到答案。对于中间的字符串,例如以左边一个字符为最小区间的左边,那么从这个中间字符的最右边开始寻找,具体判断方法见代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int a[N],num[N],na[N],nb[N];
LL ans;
int n,tem;
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1; i<=n; i++)scanf("%d",&a[i]),num[a[i]]++;
        bool flag=false;
        int val;
        for(int i=1; i<=n; i++)
        {
            if(num[i]%2)
            {
                if(flag)
                {
                    printf("0\n");
                    return 0;
                }
                flag=true;
                val=i;
            }

        }
        int tem=-1;
        for(int i=1,j=n; i<=j; i++,j--)
        {
            if(a[i]!=a[j])
            {
                tem=i;
                break;
            }
            num[a[i]]-=2;
        }
        if(tem==-1)
        {
            printf("%I64d\n",1LL*n*(n+1)/2);
            return 0;
        }
        LL ans=0;
        for(int i=tem;i<=n;i++)
        {
            na[a[i]]++;
            int j=n-i+1;
            if((i<j&&na[a[i]]*2>num[a[i]])||(i==j&&val!=a[i])||(i>j&&a[i]!=a[j]))
            {
                 ans+=(LL)tem*i;break;
            }
        }
        for(int i=n-tem+1;i>=1;i--)
        {
            nb[a[i]]++;
            int j=n-i+1;
            if((i>j&&nb[a[i]]*2>num[a[i]])||(i==j&&val!=a[i])||(i<j&&a[i]!=a[j]))
            {
                ans+=(LL)tem*j;break;
            }
        }
        ans-=(LL)tem*tem;
        printf("%I64d\n",ans);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值