Codeforces Round 1059 (Div. 3)
第一次div3赛时5题,虽然最后还剩下40多分钟,但是F一直差一点。事实证明我确实赛时写不出来F,比赛结束后F也订了好久。
A. Beautiful Average
显然,找数列最大数输出即可。
#include <bits/stdc++.h>
#define intt long long
#define N
#define debug(x) cout<<#x<<":"<<x<<" ";
using namespace std;
//using namespace __gnu_pbds;
int T,n,m;
void solve()
{
scanf("%d",&n);
int maxn=0;
for(int t=1,u1;t<=n;++t)
{
scanf("%d",&u1);
maxn=max(maxn,u1);
}
printf("%d\n",maxn);
}
int main()
{
cin>>T;
while(T--)
{
solve();
}
return 0;
}
B. Beautiful String
注意到选择的是子序列,那么我们可以直接把数列的1给删除,剩下的所有0构成的数列,或者空数列一定满足题意。
#include <bits/stdc++.h>
#define intt long long
#define N
#define debug(x) cout<<#x<<":"<<x<<" ";
using namespace std;
//using namespace __gnu_pbds;
int T,n,m;
void solve()
{
scanf("%d",&n);
string s;
cin>>s;
vector<int> v;
for(int t=0;t<s.size();++t)
{
if(s[t]=='1')
{
v.push_back(t+1);
}
}
printf("%d\n",v.size());
for(auto i:v)
{
printf("%d ",i);
}
cout<<endl;
}
int main()
{
cin>>T;
while(T--)
{
solve();
}
return 0;
}
C. Beautiful XOR
出现异或运算,回想一下异或的性质后,可以发现
x
1
⊕
x
2
⊕
.
.
.
⊕
x
i
=
a
⊕
b
x_1\oplus x_2 \oplus ...\oplus x_i=a \oplus b
x1⊕x2⊕...⊕xi=a⊕b
那么我们每次不妨直接用2的次幂进行异或,可以发现因为a<=1e9,所以运算次数绝对不会超过64次。但是还有个条件是每次的x要小于a,特判即可(这也是为什么每次用2的次幂,这样子可以使每次运算的x尽量小)
#include <bits/stdc++.h>
#define intt long long
#define N
#define debug(x) cout<<#x<<":"<<x<<" "<<endl;
using namespace std;
//using namespace __gnu_pbds;
int T,n,m;
void solve()
{
int a,b,c,d,e=1;
vector<int> v;
cin>>a>>b;
c=a^b;
d=c;
while(d)
{
if(d&1)
{
if(e>a)
{
cout<<-1<<endl;
return ;
}
v.push_back(e);
// debug(e)
}
e<<=1;
d>>=1;
}
if(!v.size())
{
cout<<0<<endl;
return ;
}
else
{
cout<<v.size()<<endl;
for(auto i:v)
cout<<i<<" ";
cout<<endl;
}
return ;
}
int main()
{
cin>>T;
while(T--)
{
solve();
}
return 0;
}
D. Beautiful Permutation
看到这一题,很显然考虑二分,当二分左右区间都有增量时,显然我们就可以确定答案。
需要注意的是,因为有限制询问次数,我们可以用大区间减去左区间从而得到右区间的询问结果,这样子可以减少询问次数。
#include <bits/stdc++.h>
#define intt long long
#define N
#define debug(x) cout<<#x<<":"<<x<<" ";
using namespace std;
//using namespace __gnu_pbds;
int T,n,m;
int yask(int u1,int l,int r)
{
int u2;
printf("%d %d %d",u1,l,r);
cout<<endl;
scanf("%d",&u2);
return u2;
}
void yans(int l,int r)
{
printf("! %d %d",l,r);
cout<<endl;
return ;
}
void solve()
{
scanf("%d",&n);
int sum1=yask(1,1,n),sum2=yask(2,1,n),len;
len=sum2-sum1;
int l=1,r=n;
while(l<r)
{
int mid=(l+r)>>1;
int now1=yask(1,l,mid),now2=yask(2,l,mid);
int now3=sum1-now1,now4=sum2-now2;
if(now2-now1>0&&now4-now3>0)
{
yans(mid-(now2-now1)+1,mid+(now4-now3));
return ;
}
if(now2-now1)
{
r=mid;
sum1=now1;
sum2=now2;
}
else
{
l=mid+1;
sum1=now3;
sum2=now4;
}
}
yans(l,r);
return ;
}
int main()
{
cin>>T;
while(T--)
{
solve();
}
return 0;
}
E. Beautiful Palindromes
此题我和大众思路并不一样。
我的思路是分成两种情况进行讨论:
第一种是全部数字都不同,这样子显然我们只需要复制粘贴一遍序列是最优的。
第二种情况是有数字是相同,这种情况下,绝对会有数字在原序列未出现,我们优先把这些数字添加,然后我们之后添加数字时,因为我们至少添加过一个原序列未出现的数字,如果回文序列不以它为中心的话,一定不存在;如果回文序列以它为中心,我们就尽量不选和原序列对应位置相同的数字即可。
#include <bits/stdc++.h>
#define intt long long
#define N 200005
#define debug(x) cout<<#x<<":"<<x<<" ";
using namespace std;
//using namespace __gnu_pbds;
int T,n,m,k;
int a[500005];
bool valid[N];
void solve()
{
scanf("%d%d",&n,&k);
for(int t=1;t<=n;++t) valid[t]=0;
vector<int> v1,v2;
deque<int> q;
for(int t=1;t<=n;++t)
{
scanf("%d",&a[t]);
if(!valid[a[t]])
{
valid[a[t]]=1;
v1.push_back(a[t]);
q.push_back(a[t]);
}
}
for(int t=1;t<=n;++t)
{
if(!valid[t])
{
v2.push_back(t);
}
}
if(!v2.size())
{
for(int t=1;t<=n&&t<=k;++t)
{
printf("%d ",a[t]);
}
cout<<endl;
return ;
}
for(int t=0;t<v2.size()&&t<k;++t)
{
printf("%d ",v2[t]);
}
for(int t=n+v2.size()+1;t<=n+k;++t)
{
if(q.front()==a[n*2+2-t])
{
printf("%d ",q.back());
q.pop_back();
}
else
{
printf("%d ",q.front());
q.pop_front();
}
}
cout<<endl;
return ;
}
int main()
{
cin>>T;
while(T--)
{
solve();
}
return 0;
}
F. Beautiful Intervals
一个重要的结论是,
m
e
x
(
M
)
=
0
,
1
,
2
mex(M)=0,1,2
mex(M)=0,1,2,不可能再有其他值,因为我们一定可以构造出
(
.
.
.
,
0
,
2
,
1
,
.
.
.
)
(...,0,2,1,...)
(...,0,2,1,...)这样的数列使得
m
e
x
<
=
2
mex<=2
mex<=2。
对于使
m
e
x
=
0
和
m
e
x
=
1
mex=0和mex=1
mex=0和mex=1的情况,前者是所有区间都有一个位置重合,那个重合的位置是0的位置;后者是要存在一个位置不是一个区间的起点和一个区间的终点,这个位置是0的位置,然后把1放到和0相邻的位置即可。
对于后者,这个很容易写错,我是参考cf官方的题解写的,不知道有没有更好的写法。
#include <bits/stdc++.h>
#define intt long long
#define N 3010
#define debug(x) cout<<#x<<":"<<x<<" ";
using namespace std;
//using namespace __gnu_pbds;
int T,n,m,sum[N],spj1[N],spj2[N];
void solve()
{
scanf("%d%d",&n,&m);
for(int t=1;t<=n;++t) sum[t]=0,spj1[t]=0,spj2[t]=0;
for(int t=1,u1,u2;t<=m;++t)
{
scanf("%d%d",&u1,&u2);
sum[u1]++;
sum[u2+1]--;
spj1[u1]=1;
spj2[u2]=1;
}
for(int t=1,now=0;t<=n;++t)
{
now+=sum[t];
if(now==m)
{
for(int i=1,u1=1;i<=n;++i)
{
if(i!=t)
{
printf("%d ",u1);
++u1;
}
else
{
printf("0 ");
}
}
return ;
}
}
for(int t=1;t<n;++t)
{
int u1,u2;
if(!spj2[t])
{
u1=t;
u2=t+1;
for(int i=1,u3=2;i<=n;++i)
{
if(i==u1) printf("0 ");
else if(i==u2) printf("1 ");
else
{
printf("%d ",u3);
++u3;
}
}
return ;
}
if(!spj1[t+1])
{
u1=t+1;
u2=t;
for(int i=1,u3=2;i<=n;++i)
{
if(i==u1) printf("0 ");
else if(i==u2) printf("1 ");
else
{
printf("%d ",u3);
++u3;
}
}
return ;
}
}
for(int t=1;t<=n;++t)
{
if(t==1) printf("0 ");
else if(t==2) printf("2 ");
else if(t==3) printf("1 ");
else printf("%d ",t-1);
}
return ;
}
int main()
{
cin>>T;
while(T--)
{
solve();
cout<<endl;
}
return 0;
}