Codeforces Round 981 (Div. 3)ABCDE
A. Sakurako and Kosuke
藕是看样例直接猜了结论😜
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e5 + 10; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); //-1 //3 //5 //7 int t; cin>>t; while(t--) { ll x; cin>>x; cout<<(x%2!=0?"Kosuke":"Sakurako")<<"\n"; } return 0; }
B. Sakurako and Water
思路:按从是负数的里面小到大遍历这条最长的主对角线,贡献就是加上这个最小的。
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e3 + 10; int a[N][N]; array<int,3>b[250010]; bool cmp(array<int,3> a,array<int,3> b) { return a[0] < b[0]; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int t; cin>>t; while(t--) { int n; cin>>n; int cnt = 0; for(int i = 1;i <= n; i++) { for(int j = 1;j <= n; j++) { cin>>a[i][j]; if(a[i][j] < 0) { b[++cnt] = {a[i][j],i,j}; } } } sort(b+1,b+1+cnt,cmp); ll ans = 0; for(int i = 1;i <= cnt; i++) { auto [v,x,y] = b[i]; if(a[x][y] >= 0)continue; ans += (-a[x][y]); int tx = x-1,ty = y-1; while(tx >= 1 && ty >= 1) { a[tx][ty] += (-a[x][y]); tx--,ty--; } tx = x+1,ty = y+1; while(tx <= n && ty <= n) { a[tx][ty] += (-a[x][y]); tx++,ty++; } a[x][y] = 0; } cout<<ans<<"\n"; } return 0; }
C. Sakurako's Field Trip
思路:因为
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e5 + 10; int a[N]; int n; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int t; cin>>t; while(t--) { cin>>n; for(int i = 1;i <= n; i++) cin>>a[i]; int ans = 0; int n1 = 0,n2 = 0; for(int i = 2;i <= n/2; i++) { n1 = 0,n2 = 0; //a[i-1] a[i] ... a[n-i+1] a[n-i+2] if(a[i] == a[i-1]) n1++; if(a[n-i+1] == a[n-i+2])//n-(i-1)+1 = n-i+2 n1++; if(a[i] == a[n-i+1]) n2++; if(a[i-1] == a[n-i+2]) n2++; if(n2 < n1) swap(a[i],a[n-i+1]); } for(int i = 1;i < n; i++) if(a[i] == a[i+1]) ans++; cout<<ans<<'\n'; } return 0; }
D. Kousuke's Assignment
思路:很容易想到前缀和,做完前缀和之后,用last记录上一次成为答案的最右边的坐标。注意0的情况直接取本身就好了。mp[i]表示i上一次出现的位置,如果mp[i]>=last说明不会重叠可以成为答案,更新last = i。因为0是一定可以的,mp[0]初始化为-1就好了。
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e5 + 10; ll a[N],s[N]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int t; cin>>t; while(t--) { int n; cin>>n; for(int i = 1;i <= n; i++) cin>>a[i]; for(int i = 1;i <= n; i++) s[i] = s[i-1]+a[i]; // for(int i = 1;i <= n; i++) // cout<<s[i]<<" "; map<ll,int>mp; int cnt = 0,last = -1; mp[0] = -1; for(int i = 1;i <= n; i++) { if(mp.count(s[i])) { if(mp[s[i]] >= last) { last = i; cnt++; } } mp[s[i]] = i; } cout<<cnt<<"\n"; } return 0; }
E. Sakurako, Kosuke, and the Permutation
题意:给你一个排列(
对于每一个
问你最少交换多少次使得这个排列是简单的。
思路:置换环(求解数组排序元素间所需最小交换次数这类问题)
思想:置换环将每个元素指向其排序后应在的位置,最终首位相连形成一个环(若数字在最终位置,则其自身成环)
对于
对于环长度
我们设
交换完一次之后变成了
这样必定可以一次修改两个数,是优于
#include <bits/stdc++.h> using namespace std; struct DSU { std::vector<int> f, siz; DSU() {} DSU(int n) { init(n); } void init(int n) { f.resize(n + 1); std::iota(f.begin(), f.end(), 0); siz.assign(n + 1, 1); } int find(int x) { while (x != f[x]) { x = f[x] = f[f[x]]; } return x; } bool same(int x, int y) { return find(x) == find(y); } bool merge(int x, int y) { x = find(x); y = find(y); if (x == y) { return false; } siz[x] += siz[y]; f[y] = x; return true; } int size(int x) { return siz[find(x)]; } }; int main() { int t; cin>>t; while(t--) { int n; cin>>n; DSU d(n); for(int i = 1;i <= n; i++) { int x; cin>>x; d.merge(i,x); } set<int>s; for(int i = 1;i <= n; i++){ d.f[i] = d.find(i); s.insert(d.f[i]); } int ans = 0; for(auto x : s) { ans += (d.siz[x]-1)/2; } cout<<ans<<"\n"; } return 0; }
或者直接模拟上述过程也是可以的:
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 1e5 + 10; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int t; cin>>t; while(t--) { int n; cin>>n; map<int,int>mp; vector<int>p(n+1); for(int i = 1;i <= n; i++){ cin>>p[i]; mp[p[i]] = i; } int ans = 0; for(int i = 1;i <= n; i++) { if(p[i] == i || p[p[i]] == i) continue; int s = mp[i],t = p[i]; swap(p[s],p[t]); mp[p[s]] = s; mp[p[t]] = t; ans++; } cout<<ans<<"\n"; } return 0; } //2 3 4 1 //2 1 4 3 //2 3 4 5 1 //2 1 4 5 3 //2 1 4 3 5
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)