[51nod1410]回文调整

  给一个序列,选择其中一个区间,这个区间内的数字顺序可以随意互换。问有多少这样的选择使得整个序列(不是选择的区间)是一个回文。
  说明:为了要使得整个序列是一个回文,可以选择一个区间对里面的数字进行调整,然后使得整个串是一个回文。
  问有多少这样的区间可供选择?

 Input
  输入共2行。
  第一行有一个整数n。(1 <= n <= 100,000)
  第二行n个整数a[i],(0<=a[i]<=n).
 Output
  对于每一组数据,输出答案占一行。

 

 

  还是跑去cf上看题解...

  先把两端回文的去掉,对于剩下的,分别求出要使序列合法,需要选择的最短前缀、后缀。然后就可以算了。。。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #define ll long long
 7 #define ui unsigned int
 8 #define ull unsigned long long
 9 const int maxn=100233,inf=1002333333;
10 int a[maxn],b[maxn],rest[maxn],need[maxn];
11 int i,j,k,n,m;
12 
13 int ra,fh;char rx;
14 inline int read(){
15     rx=getchar(),ra=0,fh=1;
16     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
17     if(rx=='-')fh=-1,rx=getchar();
18     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
19 }
20 
21 
22 int main(){register int i,j;
23     while(scanf("%d",&n)!=EOF){
24         for(i=1;i<=n;i++)a[i]=read();
25         for(m=1;(m<<1)<=n&&a[m]==a[n-m+1];m++);
26         if((m<<1)>n){printf("%lld\n",1ll*n*(n+1)>>1);continue;}
27         
28         int n1=n-((m-1)<<1);
29         memset(rest,0,(n+1)<<2),memset(need,0,(n+1)<<2);
30         for(i=1;i<=n1;i++)rest[b[i]=a[i+m-1]]++;
31         int odd=0;
32         for(i=0;i<=n;i++)odd+=rest[i]&1;
33         if(odd>(n1&1)){puts("0");continue;}
34         
35         for(i=n1;i;i--){
36             rest[b[i]]--,need[b[i]]++;
37             if((i<<1)<=n1)
38                 if(b[i]==b[n1-i+1])need[b[i]]-=2;else break;
39             if((i<<1)==n1+1)need[b[i]]--;
40             if(need[b[i]]>rest[b[i]])break;
41         }int L=i;
42         
43         memset(rest,0,(n+1)<<2),memset(need,0,(n+1)<<2);
44         for(i=1;i<=n1;i++)rest[b[i]]++;
45         for(i=1;i<=n1;i++){
46             rest[b[i]]--,need[b[i]]++;
47             if((i<<1)>n1+1)
48                 if(b[i]==b[n1-i+1])need[b[i]]-=2;else break;
49             if((i<<1)==n1+1)need[b[i]]--;
50             if(need[b[i]]>rest[b[i]])break;
51         }int R=n1-i+1;
52     //    printf("    m:%d   L:%d  R:%d\n",m,L,R);
53         printf("%lld\n",1ll*m*(m + 2*n1-L-R));
54     }
55 }
View Code

 

posted @ 2016-10-11 21:52  czllgzmzl  阅读(169)  评论(0编辑  收藏  举报