Codeforces 1178E Archaeology (鸽巢原理)
题意:
给你1e6的字符串,保证只含'a''b''c'三种字符,且相邻两个字符一定不一样
求一个大于等于n/2的回文子序列
思路:
朴素的最长回文子序列是n方的区间dp,这题显然不行,要充分利用题中所给的条件
我们发现,在任意不相交的两个区间[l,l+1]与[r,r+1]中
有两组相邻的字母,一共四个字母,而题目保证了每组两个相邻的字母肯定不同,
所以这四个字母中最多有3种字母,又因为每组字母不相同,所以这两个区间中一定有一个相同的字母
这题就搞完了
代码:
#include<iostream> #include<cstdio> #include<algorithm> //#include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 998244353; const int maxn = 2e6+100; const int maxm = 2e6+100; const int inf = 0x3f3f3f3f; //const db pi = acos(-1.0); int n; char a[maxn]; int vis[maxn]; int main(){ scanf("%s",a+1); n=strlen(a+1); int l=1,r=n; int ans = 0; while(l<=r){ //printf("%d %d\n",l,r); if(l==r){vis[l]=1;break;} if(l+1==r){vis[l]=1;break;} if(l+2==r){vis[l]=1;break;} if(a[l]==a[r]){vis[l]=vis[r]=1;} else if(a[l]==a[r-1]){vis[l]=vis[r-1]=1;} else if(a[l+1]==a[r-1]){vis[l+1]=vis[r-1]=1;} else if(a[l+1]==a[r]){vis[l+1]=vis[r]=1;} l+=2;r-=2; } for(int i = 1; i <= n; i++){ if(vis[i])printf("%c",a[i]); } return 0; } /* abcba bcb cb aba ababc baba cbacb */