持续创作,加速成长!这是我参与「掘金日新计划 · 1 月更文挑战」的第17天,点击查看活动详情
【Codeforces】Codeforces Global Round 23 A-C
题目链接
Dashboard - Codeforces Global Round 23 - Codeforces
A Maxmina
题目大意
给定一个长度为 的数字串,仅包括 0 和 1。有以下两种操作:
- 将 个数变为他们的最大值(k个数变成1个数)
- 将相邻的两个数变为他们的最小值(2个数变成1个数)
询问是否可以将这个数字串变成仅含有一个数字且为 1 的串。
思路
已知如果数字串中含有数字 1,答案为 YES,否则输出 NO。
代码
#include <bits/stdc++.h>
#define nn printf("NO\n")
#define yy printf("YES\n")
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
typedef pair<int,int> PII;
const int N=500001;
const LL mod=1000000007;
//const LL mod=998244353;
vector<int> e[N];
int f[N],x,y,z;
int n,m,k;
void bcjInit() {for (int i=1;i<=n;++i) f[i]=i;}
int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
LL gcd(LL x,LL y) {return y==0?x:gcd(y,x%y);}
int solve()
{
scanf("%d",&n);
scanf("%d",&m);
int x,flag=0;
for (int i=1;i<=n;++i)
{
scanf("%d",&x);
if (x==1) flag=1;
}
return flag;
// scanf("%d",&k);
}
int main()
{
int T=1;
for (scanf("%d",&T);T--;)
if (solve()) printf("YES\n");
else printf("NO\n");
// for (scanf("%d",&T);T--;) solve();
// solve();
return 0;
}
B Rebellion
题目大意
给定一个长度为 的数组 ,每个元素的值为 0 或 1。定义单次操作分以下三个步骤:
- 选择两个下标 且 。
- 令
- 从数组中删除 ,且数组长度 减小 1。
操作后数组元素可以大于 1。
问至少操作多少次后数组单调不降。
思路
双指针把原数组的 1 全堆到数组的末尾。
代码
#include <bits/stdc++.h>
#define nn printf("NO\n")
#define yy printf("YES\n")
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
typedef pair<int,int> PII;
const int N=500001;
const LL mod=1000000007;
//const LL mod=998244353;
vector<int> e[N];
int f[N],x,y,z;
int n,m,k;
void bcjInit() {for (int i=1;i<=n;++i) f[i]=i;}
int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
LL gcd(LL x,LL y) {return y==0?x:gcd(y,x%y);}
int a[N];
int solve()
{
scanf("%d",&n);
int ans=0;
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
for (int i=1,j=n;i<=j;)
{
if (a[i]==0) i++;
else if (a[j]==1) j--;
else
{
i++;
j--;
ans++;
}
}
printf("%d\n",ans);
return 0;
// scanf("%d",&k);
}
int main()
{
int T=1;
for (scanf("%d",&T);T--;) solve();
return 0;
}
C Permutation Operations
题目大意
对一个 到 的排列 进行 次操作,第 次操作可以选择一个下标 ,让 。一个下标可以多次被选择。
求最小化逆序对数的后缀选择方案。
思路
显然经过 次操作后逆序对数最后一定是 。
合法解很多,一种可行的方案是是给 后面所有的元素加上一个大于 的数。
代码
#include <bits/stdc++.h>
#define nn printf("NO\n")
#define yy printf("YES\n")
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
typedef pair<int,int> PII;
const int N=500001;
const LL mod=1000000007;
//const LL mod=998244353;
vector<int> e[N];
int f[N],x,y,z;
int n,m,k;
void bcjInit() {for (int i=1;i<=n;++i) f[i]=i;}
int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
LL gcd(LL x,LL y) {return y==0?x:gcd(y,x%y);}
int a[N],v[N],ans[N];
int solve()
{
scanf("%d",&n);
for (int i=1;i<=n;++i) v[i]=ans[i]=0;
int t=1;
for (int i=1,j;i<=n;++i)
{
scanf("%d",&a[i]);
v[a[i]]=1;
while (v[t]) t++;
if (t<a[i])
{
for (j=a[i]-t;ans[j];j++);
ans[j]=i+1;
}
}
for (int i=1;i<=n;++i)
if (!ans[i]) printf("1 ");
else printf("%d ",ans[i]);
printf("\n");
return 0;
}
int main()
{
int T=1;
for (scanf("%d",&T);T--;) solve();
return 0;
}