Codeforces Round #770 (Div. 2)

Codeforces Round #770 (Div. 2)

VP

A B C D E
7min 30min 63min 131min
+2 +2

排名:rk485
基准分:1967

A

800

CF1634A Reverse and Concatenate

很明显,要么能有 2 种,否则就是 1 种,简单分讨即可。
时间复杂度:O(n)

int n,k;
const int N=2e5+10;
char s[N];
void work(){
  cin>>n>>k>>(s+1);
  bool f=1;
  L(i,1,n/2)
    if(s[i]!=s[n-i+1]) f=0;
  if(f||!k) cout<<1<<'\n';
  else cout<<2<<'\n';
}

B

1400

CF1634B Fortune Telling

2B 1400 出题人怕不是有大病

题目似乎很难用常规的思路求解,考虑某些奇怪的角度切入。

明显 xx+3 的奇偶性必然不同,考虑从奇偶性入手。
对于相加运算:
假设加上 y,不管 y 的奇偶性如何,x+yx+y+3 的奇偶性必然不同。
对于异或运算:
假设异或上 y,因为 xx+3 二进制下最后一位不同,异或后也不会相同。

所以,xmod2 的值进行任意一次操作,对比 ymod2 的值即可。
因为题目保证其一有解,所以可以确定。
时间复杂度:O(n)

int n,x,y;
const int N=2e5+10;
int a[N];
void work(){
  cin>>n>>x>>y;
  int t=x%2,g=y%2;
  L(i,1,n) cin>>a[i];
  L(i,1,n) t+=a[i];
  cout<<((t%2==y%2)?"Alice":"Bob")<<'\n';
}

C

1000

CF1634C OKEA

不难想到形如 ,5,7,9,,6,8,10,12, 的情况都能满足。
首先要把无解的情况,也就是nmod2=1 时判掉。
不难想到这样为何无解,此时除非 m=1 时可以有解。
之后按照之前的状况构造即可。
时间复杂度:O(nk)

void work(){
  cin>>x>>y;int c1=0,c2=1;
  if((x&1)&&(y^1)) return cout<<"NO"<<'\n',void();
  cout<<"YES"<<'\n';
  L(i,1,x) L(j,1,y)
    if(i&1) cout<<(c1++)*2+1<<" \n"[j==y];
    else cout<<(c2++)*2<<" \n"[j==y];
}

不该被 B 吓死……

D

2000

CF1634D Finding Zero

NewbieCandidateMaster 只是 CD 的差距

对样例手搓可知,4 次查询肯定能确定 2 个绝对不是 0 的数。
将两个可能是 0 的数带上,再对之后的数进行更新,重复之前的过程即可。

int n,x,y,a[5];
int ask(int x,int y,int z){
  cout<<"? "<<x<<' '<<y<<' '<<z<<'\n';
  cl;int g;cin>>g;return g;
}void work(){
  cin>>n;int x,y,z=1,ma=0,c=0;
  a[1]=ask(2,3,4);a[2]=ask(1,3,4);
  a[3]=ask(1,2,4);a[4]=ask(1,2,3);
  L(i,1,4) ma=max(ma,a[i]);
  vector<int>p;
  L(i,1,4){
  	if(a[i]!=ma||c==2) 
  		p.push_back(i);
  	else c++;
  }x=p[0],y=p[1];
  while(z==x||z==y) z++;
  L(i,5,n){
    int X=ask(x,z,i),Y=ask(y,z,i);
    if(max(X,Y)>ma){
      ma=max(X,Y);
      if(X>Y) y=i;else x=i;
    }
  }cout<<"! "<<x<<' '<<y<<'\n';cl;
}

E

2400

CF1634E Fair Share

官方给出的解法是欧拉回路(好像),但窝太菜了,不会,没学,也就没写。

因为看到把元素分到两个集合中,还是可以想到用二分图去做。
首先可以想到,如果某个数字出现次数是奇数,就直接判为无解,这一过程可以用 std::map() 实现。

然后解决建模这个大问题,考虑加强限制。

对于每个数组分配对半这个条件,转化为每个数组中,相邻的数不得出现在同一集合。
即:对于数组 a,所有满足条件的 i,在 a2i1a2i 之间连边。

对于一半某数在左一半在右这个条件,转化为所有数中,相邻且相等的数不得出现在同一集合。
即:把所有数收集到 p,排序,所有满足条件的 i,在 p2i1p2i 之间连边。

尝试证明这样会产生一个二分图。
二分图的一个重要性质就是没有奇环。按上述方法连边,因为已经把出现奇数次的不合法情况排除了(但我赛时居然一开始没想到),所以每个点必定都只连两条边。
不难证明这样建出的图不存在奇环,所以如上建图之后跑二分图染色,之后按颜色输出方案即可。
赛时代码非常扭曲,可能参考意义不大
时间复杂度:O(nlog2n)

int m,tot;
const int N=2e5+10;
int n[N],cl[N],in[N];
vector<int>g[N];
vector<pi>a[N],p;
map<int,int>mp;
void dfs(int u,int f){
  cl[u]=f;
  for(int v:g[u]){
    if(cl[v]) continue;
    dfs(v,-f);
  }
}void work(){
  cin>>m;
  L(i,1,m){
    cin>>n[i];
    L(j,1,n[i]){
      int x;cin>>x;p.pb({x,tot});
      a[i].pb({x,tot});mp[x]++;
      in[tot]=i;
      tot++;
    }
  }sort(p.begin(),p.end());
  L(i,1,m) for(auto x:a[i])
    if(mp[F(x)]&1) return cout<<"NO",void();
  cout<<"YES"<<'\n';
  L(i,1,m) for(int j=0;j<=a[i].size()-2;j+=2){
    g[S(a[i][j])].pb(S(a[i][j+1]));
    g[S(a[i][j+1])].pb(S(a[i][j]));
  }for(int i=0;i<(int)p.size()-1;i++){
    if(F(p[i])==F(p[i+1])){
      g[S(p[i+1])].pb(S(p[i]));
      g[S(p[i])].pb(S(p[i+1]));
      i++;
    }
  }L(i,0,tot-1) if(!cl[i])dfs(i,1);
  int cnt=0;
  L(i,1,m){
    L(j,1,n[i]){
      cout<<(cl[cnt]==1?'L':'R');
      cnt++;
    }cout<<'\n';
  }
}

对了,讨论区有暴论称,F可能跟D一个难度,也许之后去逝逝看2600 的评分怕不是在逗我

posted @   AIskeleton  阅读(18)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示