题意:有一个长度为 n 的的字符串,现在给出长度1到n-1的该串前缀和后缀(混合的),求哪些串是前缀,哪些是后缀。
思路:为啥我感觉这套比赛除了E题,就C题最难.....先找到两个最长的串,假设其中一个为前缀另外一个为后缀即可。
#include<bits/stdc++.h>
using namespace std;
char pre[105],sa[105];
int n,vis[201];
struct node
{
char s[105];
int id;
bool operator<(const node& t)const
{
return strlen(s)<strlen(t.s);
}
}a[205];
int isp(char s[105])
{
int m=strlen(s);
for(int i=0;i<m;i++)
if(s[i]!=pre[i])return 0;
return 1;
}
int issa(char s[105])
{
int m=strlen(s);
for(int i=0,j=n-1-m;i<m;i++,j++)
if(s[i]!=sa[j])return 0;
return 1;
}
void print()
{
for(int i=1;i<=n*2-2;i++)
if(vis[i]==1)printf("P");
else printf("S");
}
int main()
{
cin>>n;
for(int i=1;i<=n*2-2;i++)cin>>a[i].s,a[i].id=i;
sort(a+1,a+n*2-1);
strcpy(pre,a[n*2-3].s);
strcpy(sa,a[n*2-2].s);
int flag=1;
for(int i=1;i<=n*2-2;i+=2)
{
if(isp(a[i].s)&&issa(a[i+1].s))
vis[a[i].id]=1,vis[a[i+1].id]=2;
else if(isp(a[i+1].s)&&issa(a[i].s))
vis[a[i].id]=2,vis[a[i+1].id]=1;
else flag=0;
}
if(flag)print();
else
{
strcpy(sa,a[n*2-3].s);
strcpy(pre,a[n*2-2].s);
for(int i=1;i<=n*2-2;i+=2)
{
if(isp(a[i].s)&&issa(a[i+1].s))
vis[a[i].id]=1,vis[a[i+1].id]=2;
else
vis[a[i].id]=2,vis[a[i+1].id]=1;
}
print();
}
}
D1. Great Vova Wall (Version 1)
题意:给你 n 堆砖头,你可以选择把一堆的高度+2,也可以选择把两堆高度相同的砖头高度同时+1,问是否把 n 堆砖头变得一样高。
思路:只要相邻两堆砖头高度相差的值为2的倍数,就直接成对消掉,最后如果还剩下的砖头堆超过1,那就是NO了。
#include<bits/stdc++.h>
using namespace std;
stack<int>s;
int main()
{
int n,a;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
if(s.empty())s.push(a);
else
{
if(abs(s.top()-a)%2)s.push(a);
else s.pop();
}
}
if(s.size()>1)puts("NO");
else puts("YES");
}
D2. Great Vova Wall (Version 2)
题意:同上,不过这题不能把一堆砖头高度+2,只能把相邻同高的砖头高度+1,问是否能使得所有砖头等高。
思路:发现这两种肯定不行:5 6 6,6 6 5,那我只要看是否存在一堆砖头,它的高度比前面的高(消消乐之后前面还剩下的),以及消消乐结束后只剩下一堆砖头且高度不是最高的,这两种特殊情况肯定输出NO。
#include<bits/stdc++.h>
using namespace std;
stack<int>s;
int main()
{
int n,a,mx=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
mx=max(mx,a);
if(s.empty())s.push(a);
else
{
if(a==s.top())s.pop();
else if(a>s.top())
{
puts("NO");
return 0;
}
else s.push(a);
}
}
if(s.size()>1)puts("NO");
else if(!s.empty()&&s.top()!=mx)puts("NO");
else puts("YES");
}
题意:给你n个点m条边的森林,你可以添加n-1-m条边使得森林变成一棵树,求最小的树的直径,并输出加边的方案。
思路:先求出森林每棵树的直径,然后dp一下找到每颗树的直径上的中间点,连接这些中间点即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
vector<int>G[maxn];
struct node
{
int u,len;
bool operator<(const node& t)const
{
return len>t.len;
}
}a[maxn];
int vis[maxn],d[maxn],rt,mx,cnt,ans;
void dfs(int u,int fa,int dep)
{
d[u]=dep;
vis[u]=1;
if(d[u]>d[rt])rt=u;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==fa)continue;
dfs(v,u,dep+1);
}
}
void dfs2(int u,int fa,int dep)
{
d[u]=dep;
mx=max(mx,dep);
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==fa)continue;
dfs2(v,u,dep+1);
d[u]=max(d[u],d[v]);
}
if(d[u]==mx&&dep==mx/2)
rt=u;
}
int main()
{
int n,m,u,v;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
for(int i=1;i<=n;i++)
if(!vis[i])
{
rt=i,mx=0;
dfs(i,0,0);
dfs2(rt,0,0);
a[++cnt].u=rt,a[cnt].len=mx/2+mx%2;
ans=max(ans,mx);
}
sort(a+1,a+1+cnt);
if(cnt>1)
ans=max(ans,a[1].len+a[2].len+1);
if(cnt>2)
ans=max(ans,a[2].len+a[3].len+2);
printf("%d\n",ans);
for(int i=2;i<=cnt;i++)
printf("%d %d\n",a[1].u,a[i].u);
}
题意:给你一棵树,每个点有权值ai,如果你任意选择一个点 u 作为根,你会得到一个cost=ai*dist( u , i )(i 取1到n),求出最大的cost。
思路:简单树形dp,先求出 1 为根的答案,设d[ i ]为以 i 为根的子树的总权值,如果我知道了 u 为根的答案,我想求 u 的儿子 v 为根的答案,我发现可以递推过来,设之前的答案为f[ u ],f[ v ]=f[ u ]+d[ 1 ] - 2*d[ v ] ,因为我现在的根到达 v 的子树所有点距离都减少了 1 ,答案就减少d[ v ],达到所有非 v 的子树的点的距离都增加了1,答案就增加d[ 1 ] - d[ v ]。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
typedef long long ll;
vector<int>G[maxn];
ll a[maxn],d[maxn],ans;
void dfs(int u,int fa,int dep)
{
d[u]=a[u];
ans+=a[u]*dep;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(fa==v)continue;
dfs(v,u,dep+1);
d[u]+=d[v];
}
}
void dfs2(int u,int fa,ll res)
{
ans=max(res,ans);
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(fa==v)continue;
dfs2(v,u,res+d[1]-d[v]*2);
}
}
int main()
{
int n,u,v;
cin>>n;
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,0,0);
dfs2(1,0,ans);
cout<<ans;
}