Codeforces Round #956 (Div. 2) and ByteRace 2024
CF1983
A. Array Divisibility
很快发现输出 符合题意。
B. Corner Twist
结论题。关键的充要条件是 的每一行/列的和模 后相等。证明的话,首先要想到 的操作是可以完成所有大小的子矩阵操作的,手模一下可以发现是对的。接着考虑比较暴力的方式,我们遍历 从 和 ,然后把 按对应操作修改成 ,经过这样之后前 行和 列都是可以相等的,所以也就是看最后那一列是否满足。而这个遍历顺序又是可以变化的,也就是最后剩下的行列可以是任意一行一列,所以要所有行列均满足模 结果相等。(应该是吧)
C. Have Your Cake and Eat It Too
还算简单。枚举三个人的顺序,然后把序列分成三段就行了,判断可以直接 ,但是我比较傻,还用了二分。
至于枚举顺序不需要重复粘贴六次代码,用一个 next_permutation
函数就行了。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=2*114514,M=505;
ll T;
ll n,m,k,x,a[N],b[N],c[N];
ll s[N][4];
ll id[3]={1,2,3},al[4],ar[4];
void solve(){
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i],s[i][1]=s[i-1][1]+a[i];
for(int i=1;i<=n;++i) cin>>b[i],s[i][2]=s[i-1][2]+b[i];
for(int i=1;i<=n;++i) cin>>c[i],s[i][3]=s[i-1][3]+c[i];
ll sum=s[n][1],k=ceil(sum*1.0/3);
id[0]=1,id[1]=2,id[2]=3;
do{
ll l=1,r=n;
ll p1=0,p2=0,p3=n;
while(l<=r){
ll mid=(l+r)>>1;
if(s[mid][id[0]]-s[0][id[0]]>=k) r=mid-1,p1=mid;
else l=mid+1;
}
if(p1>=n-1||s[p1][id[0]]-s[0][id[0]]<k) continue;
l=p1+1,r=n;
while(l<=r){
ll mid=(l+r)>>1;
if(s[mid][id[1]]-s[p1][id[1]]>=k) r=mid-1,p2=mid;
else l=mid+1;
}
if(p2==n||s[p2][id[1]]-s[p1][id[1]]<k) continue;
if(s[n][id[2]]-s[p2][id[2]]<k) continue;
al[id[0]]=1,ar[id[0]]=p1;
al[id[1]]=p1+1,ar[id[1]]=p2;
al[id[2]]=p2+1,ar[id[2]]=n;
for(int i=1;i<=3;++i) cout<<al[i]<<" "<<ar[i]<<" ";
cout<<'\n'; return;
}while(next_permutation(id,id+3));
cout<<"-1\n";
}//包赢的
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>T;
while(T--) solve();
return 0;
}
D. Swap Dilemma
发现操作和值的大小没有关系,可以把 赋值为其在 中的位置,然后直接求逆序对个数,如果为奇数就无解。
考虑从交换 这种操作入手,类似于 B 题,这种操作是可以完成其他所有取值的操作的,而这种操作执行时只会改变 逆序对的数量,并且同时改变其数量奇偶性,那么可以猜测,如果 两数列初始时逆序对数量奇偶性不同时无解,否则有解,然后便可以转化成上面的结论。正确性的话不想证,手模发现是对的。
E. I Love Balls
不想写了
頑張って