c-Plasticine zebra
题目链接:http://codeforces.com/contest/1025/problem/C
只要反应过来了这个其实求的是这个串组成的环的最长的间隔最大值就好做了
直接延长一倍处理环,然后dp[i]表示处理到i这点最长的间隔值的最大是多少就行了
#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int maxn=2e5+5;
const int MOD=1e9+7;
char s[maxn];
int dp[maxn];
int main()
{
while(cin>>s)
{
memset(dp,0,sizeof dp);
int len=strlen(s);
for(int i=0;i<len;i++)s[i+len]=s[i];
int n=len<<1;
int Max=-1;
dp[0]=1;
for(int i=1;i<n;i++)
{
if(s[i]!=s[i-1])dp[i]=dp[i-1]+1;
else dp[i]=1;
Max=max(Max,dp[i]);
}
cout<<min(Max,len)<<endl;
}
}
D-Recovering BST
题目链接:http://codeforces.com/contest/1025/problem/D
哇~竟然是个区间dp,这怎么想到的T_T
dp[i][j]表示在区间[i,j]内的数能不能组成题目要求的二叉树
长的区间由短的区间递推过来,两重循环枚举区间,再一次循环枚举断点,很经典的三重循环的区间dp,但是怎么转移的喃?
就是假如一个点是根节点,如果他左儿子连的点和右儿子连的点就阔以组成一个合法的区间~
感觉还是不是理解得很好,先记下来再说
#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int maxn=700+5;
const int MOD=1e9+7;
const int inf=1e9;
int a[maxn];
bool G[maxn][maxn];
//L[i][k]表示以k为根节点,向左走能不能连到第i个点
//R[k][j]表示以k为根节点,向右走能不能连到第j个点
bool L[maxn][maxn],R[maxn][maxn],dp[maxn][maxn];//dp[i][j]表示[i,j]区间内的数阔以满足条件
int main()
{
int N;
cin>>N;
for(int i=1;i<=N;i++)cin>>a[i],L[i][i]=R[i][i]=1;
for(int i=1;i<=N;i++)//先打个表出来,因为后面会经常看某两个点阔步阔以连
{
for(int j=1;j<=N;j++)
{
if(i==j)continue;
if(__gcd(a[i],a[j])==1)continue;
G[i][j]=1;
}
}
for(int len=0;len<N;len++)
{
for(int i=1;i+len<=N;i++)
{
int j=i+len;
for(int k=i;k<=j;k++)
{
if(L[i][k]&&R[k][j])
{
dp[i][j]=1;
if(G[i-1][k])R[i-1][j]=1;//向左扩展
if(G[k][j+1])L[i][j+1]=1;//向右扩展
}
}
}
}
if(dp[1][N])cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}