吉哥系列故事——完美队形II(马拉车算法)
Posted 哟吼!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了吉哥系列故事——完美队形II(马拉车算法)相关的知识,希望对你有一定的参考价值。
吉哥又想出了一个新的完美队形游戏!
假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形:
1、挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的;
2、左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然如果m是奇数,中间那个人可以任意;
3、从左到中间那个人,身高需保证不下降,如果用H表示新队形的高度,则H[1] <= H[2] <= H[3] .... <= H[mid]。
现在吉哥想知道:最多能选出多少人组成新的完美队形呢?
假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形:
1、挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的;
2、左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然如果m是奇数,中间那个人可以任意;
3、从左到中间那个人,身高需保证不下降,如果用H表示新队形的高度,则H[1] <= H[2] <= H[3] .... <= H[mid]。
现在吉哥想知道:最多能选出多少人组成新的完美队形呢?
Input 输入数据第一行包含一个整数T,表示总共有T组测试数据(T <= 20);
每组数据首先是一个整数n(1 <= n <= 100000),表示原先队形的人数,接下来一行输入n个整数,表示原队形从左到右站的人的身高(50 <= h <= 250,不排除特别矮小和高大的)。Output 请输出能组成完美队形的最多人数,每组输出占一行。Sample Input
2 3 51 52 51 4 51 52 52 51
Sample Output
3 4
题意:
就是让你找到一个最长回文子串,如果这个串是偶数,那么他的左边一半就要满足i<j且Ai<=Aj,也就是非严格递增类型
如果是奇数,那么中间那个数大小可以不受限制
题解:
就是在马拉车算法里面加一个判断,只是我前边那一种写的太麻烦了,所以超时了
具体看代码:
1 //#include<stdio.h> 2 //#include<string.h> 3 //#include<iostream> 4 //#include<algorithm> 5 //#include<set> 6 //using namespace std; 7 //const int maxn=300005; 8 //const int INF=0x3f3f3f3f; 9 //const int mod=998244353; 10 //int str[maxn],s[maxn]; 11 //int len,Len[maxn]; 12 //void init() 13 //{ 14 // memset(str,0,sizeof(str)); 15 // int k=0; 16 // str[k++]=10000; 17 // for(int i=0;i<len;++i) 18 // str[k++]=1000,str[k++]=s[i]; 19 // str[k++]=1000; 20 // len=k; 21 //} 22 //int manacher() 23 //{ 24 // Len[0]=0; 25 // int sum=0; 26 // int mx=0,id; 27 // for(int i=1;i<len;++i) 28 // { 29 // if(i<mx) Len[i]=min(mx-i,Len[2*id-i]); 30 // else Len[i]=1; 31 // while(str[i-Len[i]]==str[i+Len[i]]) Len[i]++; 32 // if(Len[i]+i>mx) 33 // { 34 // mx=Len[i]+i; 35 // id=i; 36 // int flag=0; 37 // if((Len[i]-1)%2) 38 // { 39 // if(Len[i]-1>=5) 40 // for(int j=i-4;j>j-Len[i];j-=2) 41 // { 42 // if(str[j]>str[j+2]) 43 // { 44 // flag=1; 45 // break; 46 // } 47 // } 48 // } 49 // else 50 // { 51 // if(Len[i]-1>=4) 52 // for(int j=i-3;j>j-Len[i];j-=2) 53 // { 54 // if(str[j]>str[j+2]) 55 // { 56 // flag=1; 57 // break; 58 // } 59 // } 60 // } 61 // if(!flag) 62 // sum=max(sum,Len[i]); 63 // } 64 // } 65 // return sum-1; 66 //} 67 //int main() 68 //{ 69 // int t; 70 // scanf("%d",&t); 71 // while(t--) 72 // { 73 // memset(s,0,sizeof(s)); 74 // scanf("%d",&len); 75 // for(int i=0;i<len;++i) 76 // scanf("%d",&s[i]); 77 // init(); 78 // printf("%d\n",manacher()); 79 // } 80 // return 0; 81 //} 82 #include<stdio.h> 83 #include<string.h> 84 #include<iostream> 85 #include<algorithm> 86 #include<set> 87 using namespace std; 88 const int maxn=300005; 89 const int INF=0x3f3f3f3f; 90 const int mod=998244353; 91 int str[maxn],s[maxn]; 92 int len,Len[maxn]; 93 void init() 94 { 95 memset(str,0,sizeof(str)); 96 int k=0; 97 str[k++]=-1; 98 for(int i=0;i<len;++i) 99 str[k++]=0,str[k++]=s[i]; 100 str[k++]=0; 101 len=k; 102 } 103 void manacher() 104 { 105 Len[0]=0; 106 int sum=0; 107 int id,mx=0; 108 for(int i=1;i<len;++i) 109 { 110 if(i<mx) Len[i]=min(mx-i,Len[2*id-i]); 111 else Len[i]=1; 112 int Min; 113 if(str[i] > 0) Min = str[i]; 114 else Min = str[i + 1]; 115 while(str[i - Len[i]] == str[i + Len[i]] && str[i - Len[i]] <= Min) { 116 //printf("are you here?\n"); 117 if(str[i - Len[i]] > 0) 118 Min = str[i - Len[i]]; 119 if(i + Len[i] > mx) { 120 mx = i + Len[i]; 121 id = i; 122 } 123 Len[i]++; 124 } 125 } 126 int ans = 0; 127 for(int i = 1; i < len; i++) ans = max(ans, Len[i]); 128 printf("%d\n", ans - 1); 129 } 130 // if(Len[i]+i>mx) 131 // { 132 // mx=Len[i]+i; 133 // id=i; 134 // int flag=0; 135 // if((Len[i]-1)%2) 136 // { 137 // if(Len[i]-1>=5) 138 // for(int j=i-4;j>j-Len[i];j-=2) 139 // { 140 // if(str[j]>str[j+2]) 141 // { 142 // flag=1; 143 // break; 144 // } 145 // } 146 // } 147 // else 148 // { 149 // if(Len[i]-1>=4) 150 // for(int j=i-3;j>i-Len[i];j-=2) 151 // { 152 // if(str[j]>str[j+2]) 153 // { 154 // flag=1; 155 // break; 156 // } 157 // } 158 // } 159 // if(!flag) 160 // sum=max(sum,Len[i]); 161 // } 162 // } 163 // return (sum-1); 164 //} 165 int main() 166 { 167 int t; 168 scanf("%d",&t); 169 while(t--) 170 { 171 scanf("%d",&len); 172 for(int i=0;i<len;++i) 173 scanf("%d",&s[i]); 174 init(); 175 manacher(); 176 //printf("%d\n",); 177 } 178 return 0; 179 }
以上是关于吉哥系列故事——完美队形II(马拉车算法)的主要内容,如果未能解决你的问题,请参考以下文章
hdu 4513 吉哥系列故事——完美队形II (manachar算法)
HDU 4513 吉哥系列故事——完美队形II (Manacher变形)
HDU 4513 吉哥系列故事――完美队形II(Manacher)