西游签到
思路:
使用字符串reverse()函数
代码:
#include<bits/stdc++.h>
using namespace std;
int T;
string s,t;
int l,r;
int main()
{
cin>>T;
while(T--)
{
cin>>s>>t;
l=0,r=s.size()-1;
while(l<s.size()&&s[l]==t[l])
{
l++;
}
if(l==r+1)
{
cout<<"Y"<<endl;
continue;
}
while(r>0&&s[r]==t[r])
{
r--;
}
reverse(s.begin()+l,s.begin()+r+1);
if(s==t)
cout<<"Y"<<endl;
else
cout<<"N"<<endl;
}
return 0;
}
斩断灵腾
思路:
贪心+dfs
将结点的子树从大到小进行排列,把各个小的节点合并
即算最小区域树时,怎样合能够给接下来更多机会
在本题中,所求的是最小区域树,可以计算砍了n刀,区域数就是n+1块,因为这里是连通块
难点:在连通图中如何通过dfs计算根节点个数
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+1;
int n,m;
vector<int> gr[N];
//存放结点个数
int f[N];
int ans;
void dfs(int u,int fa)
{
f[u]=1;
vector<int> t;
for(auto v:gr[u])
{
if(v==fa)
continue;
//对每一颗子树做dfs
dfs(v,u);
//dfs结束后每一个字结点所谓根节点的子树大小已算出
t.push_back(f[v]);
}
//排序
sort(t.begin(),t.end());
//
for(int i=0;i<t.size();i++)
{
if(f[u]+t[i]<=m)
f[u]+=t[i];
else
//砍掉前面已经加上的结点
ans+=t.size()-i;
break;
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
//将每一个的所有相邻点都存入vector向量里
gr[u].push_back(v);
gr[v].push_back(u);
}
//从1号节点作为根节点开始搜索
//参数:本身,父节点
dfs(1,0);
cout<<ans+1;
return 0;
}
符咒封印
思路:
前缀和+后缀和
使用公式推理,