## F.优秀字符串
题意:有n个字符串找出优秀字符串的个数。优秀字符串的定义:长度为5,第三个字符和第五个字符相同,前四个字符互不相同。
分析:直接模拟即可
代码:
```
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;int ans=0;
while(n--){
string s;cin>>s;
int len=s.size();
if(len==5&&s[0]!=s[1]&&s[0]!=s[2]&&s[0]!=s[3]&&s[1]!=s[2]&&s[1]!=s[3]&&s[2]!=s[3]&&s[2]==s[4]){
ans++;
}
}
cout<<ans<<endl;
}
```
## M.有效算法
题意:给定数组a和b,将ai 变成满足|ai−x|≤k×bi 的任意整数x。
求出最小的非负整数k,使得ai所有的数相等。
分析:二分查找符合条件的k,每查找一个k都会遍历数组a,并且x会有一定区间,只要每次区间和上一次区间相交,就继续遍历,如果中途有不相交,就是不符合要求。
代码:
```
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+10;
ll a[N],b[N],n;
ll f(ll x){
ll x1=-0x3f3f3f3f,x2=0x3f3f3f3f;
for(int i=1;i<=n;i++){
ll c=a[i]-x*b[i];
ll d=a[i]+x*b[i];
if(d<x1||c>x2)return 0;
x2=min(x2,d);
x1=max(c,x1);
if(x1>x2)return 0;
}
return 1;
}
void sol(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
ll l=0,r=0x3f3f3f3f;
while(l<r){
ll mid=(l+r)/2;
if(f(mid)==1)r=mid;
else l=mid+1;
}
cout<<l<<endl;
}
int main(){
int t;cin>>t;
while(t--)sol();
return 0;
}
```
## L. Toxel 与 PCPC II(dp)
题意:一共有n行,m行有bug,ai代表第i行有bug,如果i行内存在bugx个,则需要x^4秒来修复,运行i行代码需要i秒
分析:设dpi为前i行最少需要的时间。由于四次方的函数增长速度极快,选取向上四五十行即可。核心代码:
```
dp[i]=min(dp[i],dp[j]+a[i]+1ll*(i-j)*(i-j)*(i-j)*(i-j));
```
代码:
```
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[N],dp[N];
int main(){
int n,m;cin>>n>>m;
for(int i=1;i<=m;i++)cin>>a[i];
for(int i=1;i<=m;i++)dp[i]=1e18;
for(int i=1;i<=m;i++){
for(int j=i-1;j>=max(0,i-50);j--){
dp[i]=min(dp[i],dp[j]+a[i]+1ll*(i-j)*(i-j)*(i-j)*(i-j));
}
}
cout<<dp[m]<<endl;
return 0;
}
```
K.树上问题
题意:有一颗由n个节点组成的无根树,美丽节点:该节点作为根时,对于除根节点以外的所有节点,其 点权都不小于其父亲节点的点权的 二分之一。计算多少个美丽节点。
分析:no数组为以该点为根,整棵树中不能通过的路径数量,dfs1存储no,dfs2将no数组中原本存储的以该点为根的子树中不能通过的路径数量更新为以该点为根的整棵树不能通过的路径数量
代码:
```
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,ans=0,no[N],a[N];
vector<int>p[N];
int dfs1(int u,int v){
for(auto x:p[u]){
if(x==v)continue;
no[u]+=dfs1(x,u)+(a[x]*2<a[u]);//更新当前节点 u 的符合条件的节点数量
}
return no[u];
}
void dfs2(int u,int v){
ans+=(no[u]==0);//儿子们没有一个不符合条件
for(auto x:p[u]){
if(x==v)continue;
no[x]=no[u]-(a[x]*2<a[u])+(a[u]*2<a[x]);//更新子节点 x 的符合条件的节点数量
dfs2(x,u);
}
}
void sol(){
cin>>n;
ans=0;
for(int i=1;i<=n;i++){
p[i].clear();
no[i]=0;
}
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=2;i<=n;i++){
int u,v;cin>>u>>v;
p[u].push_back(v);
p[v].push_back(u);//建树
}
dfs1(1,0);
dfs2(1,0);
cout<<ans<<endl;
}
int main(){
int t;cin>>t;
while(t--)sol();
return 0;
}
```