Codeforces Round 998 (Div. 3)
A
给了\(a_1,a_2,a_4,a_5\),求\(a_3\)使得满足斐波拉契数列的关系式的个数
solution:假设\(a_3\)满足一个关系,然后再去试其他关系式是否正确
B
给一个二维数组,同一行的数可以交换,寻找一种枚举顺序,使得每一列都按照这样的顺序取出来的数,全部都单调递增
如何确定顺序:
每一行都排序,我们一定要确保第一列都是单调递增的,否则后面的满足题意也没用,所以要排序
如何确定顺序是对的:
如果依次取出来的数都单调递增,那么同一行的数(排序后)一定满足,单调递增且公差为n(行数)
#include<bits/stdc++.h>
using namespace std;
int t;
int n,m;
const int maxn=2e3+10;
int a[maxn][maxn];
int b[maxn];
bool book[maxn];
int nt[maxn];
void solve(){
cin>>n>>m;
queue<int> ans;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j) cin>>b[j];
sort(b+1,b+1+m);
for(int j=1;j<=m;++j) a[i][j]=b[j];
}
for(int i=1;i<=n;++i){
int minn=1e5+10,p;
for(int j=1;j<=n;++j){
if(book[j]==0 && minn>a[j][1]){
p=j;
minn=a[j][1];
}
}
book[p]=1;
for(int j=1;j<m;++j)
if(a[p][j]+n!=a[p][j+1]){
puts("-1");
return ;
}
ans.push(p);
}
while(!ans.empty()){
cout<<ans.front()<<" ";
ans.pop();
}
cout<<"\n";
return ;
}
int main(){
cin>>t;
while(t--){
solve();
memset(book,0,sizeof(book));
}
return 0;
}
C
给定偶数长度的一组数,A,B轮流选一个数,如果和等于K,那么score+1
A想要减少score,B想要增加score
对于数组中的数,我们可以分成两类,一种可以和其他的数组成k,一种则不然
所以对于A,首先会选择不能构成k的数,此时B为了不减少可以构成k的数,也选择不能构成k的数
当第一类数选完了,A只能选择可以构成k的数,B此时要选择与A选的数相加等于k的数
这样满足题意
#include<bits/stdc++.h>
using namespace std;
int t;
int n,k;
const int maxn=2e5+10;
int x[maxn];
void solve(){
cin>>n>>k;
for(int i=1;i<=n;++i) cin>>x[i];
sort(x+1,x+1+n);
int a=0;
for(int i=1,j=n;i<j;++i){
while(x[i]+x[j]>k && j>i){
--j;
}
if(x[i]+x[j]==k && i!=j) a+=2,--j;
}
int b=n-a;
if(b%2) a-=1;
cout<<a/2<<"\n";
}
int main(){
cin>>t;
while(t--){
solve();
}
return 0;
}
D
给了一个数组,可以进行这样的操作:减去相邻两个数的最小值
这样操作后是否可以使得数组单调递增(可以等于
显然如果在操作过程中\(a_i>a_{i+1}\),数组无论如何操作都会单调递增
所以模拟一遍操作过程即可
#include<bits/stdc++.h>
using namespace std;
int t;
int n,k;
const int maxn=2e5+10;
int x[maxn];
void solve(){
cin>>n;
for(int i=1;i<=n;++i) cin>>x[i];
for(int i=2;i<=n;++i){
if(x[i]<x[i-1]) {
puts("NO");
return ;
}
else {
x[i]-=x[i-1];
x[i-1]=0;
if(x[i]>x[i+1] && i!=n){
puts("NO");
return ;
}
}
}
puts("YES");
return ;
}
int main(){
cin>>t;
while(t--){
solve();
}
return 0;
}
E
给出两个图F,G,可以任意删去,增加F中的边
是否经过操作后,使得F,G中的顶点之间,存在的连通性相同
我们只考虑连通性,不关心具体的边怎么实现,这时就可以用并查集来实现
- 如果F中两点之间连通但G中不,所以删去一条边
- 如果G中两点之间连通但F中不,所以增加一条边
先建立G图的连通性,再根据G图,再建立F图
#include<bits/stdc++.h>
using namespace std;
int n,m1,m2;
int t;
const int maxn=4e5+10;
int f1[maxn],f2[maxn];
struct node{
int u,v;
}e1[maxn],e2[maxn];
int find1(int x){
if(x!=f1[x])return f1[x]=find1(f1[x]);
return x;
}
int find2(int x){
if(x!=f2[x])return f2[x]=find2(f2[x]);
return x;
}
void init(){
cin>>n>>m1>>m2;
for(int i=1;i<=n;++i) f1[i]=f2[i]=i;
for(int i=1;i<=m1;++i){
cin>>e1[i].u>>e1[i].v;
}
for(int i=1;i<=m2;++i) {
cin>>e2[i].u>>e2[i].v;
int u=find2(e2[i].u);
int v=find2(e2[i].v);
f2[u]=v;
}
}
void solve(){
init();
int ans=0;
for(int i=1;i<=m1;++i){
int u=e1[i].u,v=e1[i].v;
if(find2(u)!=find2(v))++ans;
else f1[find1(u)]=find1(v);
}
for(int i=1;i<=m2;++i){
int u=find1(e2[i].u),v=find1(e2[i].v);
if(u!=v){
++ans;
f1[u]=v;
}
}
cout<<ans<<endl;
}
int main(){
cin>>t;
while(t--){
solve();
}
return 0;
}

浙公网安备 33010602011771号