A. Equidistant Letters
题目链接
https://codeforces.com/contest/1626/problem/A
题目大意
给定字符串s,保证由小写字母组成且每个字母出现不超过两次,请你重新排列,使得所有出现两次的字符距离相同
分析
- 不难想到,距离可以取1,即为相邻
- 直接将原字符串排序,则若只出现一次,不考虑,若出现两次,则相距都为1
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#define ll long long
using namespace std;
const int mo=998244353;
const int maxn=2e5+10;
int t=1;
char s[100];
int main(){
scanf("%d",&t);
while(t--){
cin>>s;
sort(s,s+strlen(s));
cout<<s<<endl;
}
}
B. Minor Reduction
题目链接
https://codeforces.com/contest/1626/problem/B
题目大意
给定x(10 ≤ x<10200000),有且只有一次机会,将相邻两位相加并放回原位置
例如 10057 可以相加前两位变成1057,可以相加后两位变成10012
求可能的最大值
分析
- 不难想到分类讨论:能够保持原位数或不能保持原位数,保持原位数的数一定比不能保持原位数大
-
- 如果保持原位数,则证明存在相邻的正整数ab,a+b≥10
- ab相加之后比原数小
- 从后向前寻找第一个可加的两位数,相加即可
-
- 如果不能保持原位数,从前向后看,合并是把两位数加起来,使得这位数更大
- 直接加前两个数即可
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<string>
#include<ctime>
#include<list>
#define ll long long
using namespace std;
const int mo=998244353;
const int maxn=2e5+10;
int t=1;
char s[200010];
int main(){
scanf("%d",&t);
while(t--){
cin>>s;
int len=strlen(s);
int f=0;
for(int i=len-1;i>=1;i--){
if(s[i]+s[i-1]-'0'-'0'>=10){
f=1;
for(int j=0;j<=i-2;j++) printf("%c",s[j]);
printf("%d",s[i]+s[i-1]-'0'-'0');
for(int j=i+1;j<len;j++) printf("%c",s[j]);
printf("\n");
break;
}
}
if(f)continue;
printf("%d",s[0]+s[1]-'0'-'0');
for(int i=2;i<len;i++) printf("%c",s[i]);
printf("\n");
}
}
C. Monsters And Spells
题目链接
https://codeforces.com/contest/1626/problem/C
题目大意
你会一种法术,每秒可以耗费x精力造成x伤害,但是每秒造成的伤害只能是1或前一秒造成的伤害+1
现在要求在ki时刻至少造成hi伤害(1≤hi≤ki≤109 ,i≤100)
求花费精力最小值
分析
- 可以从前向后考虑,如果遍历到某时刻发现之前统计的开始时刻太晚了就更新开始时刻
- 如果之前更新的结束时刻开始没法达到现在的要求,就更新结束时刻
- 重复直到所有要求都满足
代码
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<string>
#include<ctime>
#include<list>
#define ll long long
using namespace std;
const int mo=998244353;
const int maxn=110;
int t=1,n,h[maxn],k[maxn];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",k+i);
for(int i=1;i<=n;i++) scanf("%d",h+i);
ll ans=0;
int l=1;
while(l<=n){
int st=k[l]-h[l]+1,ed=k[l],r=l;
for(int i=l+1;i<=n;i++){
if(k[i]-h[i]+1<=st){
st=k[i]-h[i]+1;
ed=k[i];
r=i;
}
if(k[i]-h[i]+1<=ed){
ed=k[i];
r=i;
}
}
// printf("\n%d - %d\n",st,ed);
ll len=ed-st+1;
ans+=len*(len+1)/2;
l=r+1;
}
cout<<ans<<endl;
}
}
D. Martial Arts Tournament
题目链接
https://codeforces.com/contest/1626/problem/D
题目大意
有n人比赛,分为三组:小于x的,大于y的,剩下的(要求x<=y)
每组必须有2的非负整数次幂的人,请问最少要加多少人
分析
- 考虑从前向后,从后向前枚举每个2的整数幂,分别计算出三组人数,最后计算出缺少的人数
- 考虑时间,可以预处理每个参加人数实际不用再加入的人数
代码
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<string>
#include<ctime>
#include<list>
#define ll long long
#define max(a,b) (a>b?a:b)
using namespace std;
const int mo=998244353;
const int maxn=200010;
int t=1,n,a[maxn],pre[maxn],after[maxn],s;
int main(){
scanf("%d",&t);
while(t--){
memset(a,0,sizeof(a));
memset(pre,0,sizeof(pre));
memset(after,0,sizeof(after));
scanf("%d",&n);
for(int i=1,x;i<=n;i++){
scanf("%d",&x);
a[x]++;
}
s=0;
for(int i=1;i<=n;i++){
for(int j=s;j<s+a[i];j++)
pre[j]=s;
s+=a[i];
}
s=0;
for(int i=n;i>=1;i--){
for(int j=s;j<s+a[i];j++)
after[j]=s;
s+=a[i];
}
int ans=(1<<20);
for(int p=1;p<=n;p<<=1)
for(int q=1;q<=n;q<<=1){
int x=pre[p],y=after[q];
int mid=1;
while(mid<n-x-y)mid<<=1;
ans=min(ans,p+q+mid-n);
}
printf("%d\n",ans);
}
}
E. Black and White Tree
题目链接
https://codeforces.com/contest/1626/problem/E
题目大意
一棵树上有大于2个黑点
现在你在某点上,你可以选择一个黑点,向它走一步,但相邻两部不能选同一个黑点,请问你从所有点出发,是否可以走到任意一个黑点
分析
- 显然黑点本身一定可以
- 显然距离黑点为1的点一定可以
- 对于某一点,如果以它为根,任意子树的根可以,且这个子树内部有两个以上黑点,那么这个点可以
- 两遍dfs即可解决问题
代码
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<string>
#include<ctime>
#include<list>
#define ll long long
#define max(a,b) (a>b?a:b)
using namespace std;
const int mo=998244353;
const int maxn=300010;
int n,ans[maxn],cnt[maxn],a[maxn],sum;
vector<int> E[maxn];
void dfs1(int u,int fa){
cnt[u]=a[u];
for(int i=0;i<E[u].size();i++){
int v=E[u][i];
if(v==fa) continue;
dfs1(v,u);
cnt[u]+=cnt[v];
if(cnt[v]>=2 && ans[v])
ans[u]=1;
}
}
void dfs2(int u,int fa){
for(int i=0;i<E[u].size();i++){
int v=E[u][i];
if(v==fa) continue;
if(sum-cnt[v]>=2 && ans[u])
ans[v]=1;
dfs2(v,u);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
sum+=a[i];
}
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
E[u].push_back(v);
E[v].push_back(u);
}
for(int i=1;i<=n;i++)
if(a[i]){
ans[i]=1;
for(int j=0;j<E[i].size();j++)
ans[E[i][j]]=1;
}
dfs1(1,1);
dfs2(1,1);
for(int i=1;i<=n;i++) printf("%d ",ans[i]);
}