目录
A. Polycarp's Pockets
B. Binary String Constructing
C. Intense Heat
D. Coins and Queries
E. Tree Constructing
F. Abbreviation
A. Polycarp's Pockets
记录数量可以直接开一个桶即可然后求最大值
void solve(){
cin>>n;
vector<int> ton(105);
int ans=0;
while(n--){
int x; cin>>x;
ton[x]++;
ans=max(ans,ton[x]);
}
cout<<ans<<endl;
return ;
}
B. Binary String Constructing
先按照01010这样的方式把题目要求构造出来然后往中间插入01即可这样答案不会变化
void solve(){
int a,b,n; cin>>a>>b>>n;
vector<int> s(n+5);
if(b>a) s[1]=1,b--;
else a--;
for(int i=2;i<=n+1;i++){
s[i]=s[i-1]^1;
if(s[i]) b--;
else a--;
}
for(int i=1;i<=n+1;i++){
cout<<s[i];
if(s[i]) while(b) cout<<1,b--;
else while(a) cout<<0,a--;
}
return ;
}
C. Intense Heat
暴力前缀和统计最大平均值即可
void solve(){
cin>>n>>m;
vector<int> a(n+5);
for(int i=1;i<=n;i++) cin>>a[i],a[i]+=a[i-1];
double res=0;
for(int i=1;i<=n;i++)
for(int j=i+m-1;j<=n;j++)
res=max(res,1.0*(a[j]-a[i-1])/(j-i+1));
cout<<LF(7)<<res<<endl;
return ;
}
D. Coins and Queries
类似二进制从大到小取满整个数即可
void solve(){
cin>>n>>m;
vector<int> cnt(33);
for(int i=1;i<=n;i++){
int x; cin>>x;
cnt[log2(x)]++;
}
while(m--){
int x; cin>>x;
int ans=0;
for(int i=31;i>=0;i--){
int t=min(x/(1<<i),cnt[i]);
ans+=t;
x-=(1<<i)*t;
}
if(x) ans=-1;
cout<<ans<<endl;
}
return ;
}
E. Tree Constructing
构造一棵树我们可以发现如果是又满足的一定是一条直径是d的我们不妨直接把直径构造出来,然后在其中的点加入限制条件之后直接构造,注意题目的意思是构造出来的树直径就是d所以按照题目要求然后对其中的点扩充即可
vector<PII> ans;
void dfs(int u,int now,int d){
if(now==d) return ;
for(int i=1;i<=k-1-(now==0)&&cnt<n;i++){//初始进来的时候是中间节点表示以及少了两个度了
cnt++;
ans.push_back({u,cnt});
dfs(cnt,now+1,d);
}
}
void solve()
{
cin>>n>>d>>k;
if(n-1<d){// 表示建立不了这枚长
cout<<"NO"<<endl;
return ;
}// n个点建立 n-1 为最长的直径
if(k==1){// 特殊情况特殊判断
if(n==2&&d==1){
cout<<"YES"<<endl;
cout<<1<<' '<<2<<endl;
}
else cout<<"NO"<<endl;
return ;
}
for(int i=1;i<=d;i++){
ans.push_back({i,i+1});
}
cnt=d+1;
for(int i=1;i<=d+1;i++)
dfs(i,0,min(i-1,d-i+1));// 表示当前的还可以构造的深度
if(cnt<n){
cout<<"NO"<<endl;
}
else{
cout<<"YES"<<endl;
for(auto&[a,b]:ans) cout<<a<<' '<<b<<endl;
}
return ;
}
F. Abbreviation
整个题目注意题目意思,以及数据范围(300-500)一般都是的时间复杂度来解决,接着我们要的是找到一段相同的然后把整个里面相同的进行缩写处理,不妨先把整个用vector<string> 存储起来,接着我们要考虑的就是相同的长度是多少,接着考虑从什么位置开始,我们 由此可以设置状态
表示 状态表示 以第i个结尾的 和以第j个结尾的最长相同后缀长度是多少这样就满足了什么位置开始长度是多少,接着枚举位置和长度来求解即可
vector<string> a;
void solve(){
a.push_back(" ");
cin>>n;
int tol=0;
for(int i=1;i<=n;i++){
string s; cin>>s;
a.push_back(s);
tol+=s.size();
}
tol+=n-1;// 求出总空间需求
int ans=tol;
// 状态表示 以第i个结尾的 和以第j个结尾的最长相同后缀长度是多少
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(a[i]==a[j])
dp[i][j]=dp[i-1][j-1]+1;
for(int i=n;i>=1;i--){// 以i为结尾
int sum=0;// 长度
for(int d=1;i-d>=0;d++){
sum+=a[i-d+1].size();
int cnt=0;
for(int j=i-d;j>=1;)// j开始
if(dp[j][i]>=d){
j-=d;
cnt++;
}
else j--;
if(cnt){
cnt++;
int now=tol-sum*cnt+cnt;
//对于整个缩写减少的是字母占据的位置,同时由于空格等于字母-1所以后面还要加一个1
// cnt 个所以要加上cnt个1
ans=min(ans,now);
}
}
}
cout<<ans<<endl;
return ;
}