Codeforces Round 962 (Div. 3)

题目链接:Codeforces Round 962 (Div. 3)

总结:ABC秒过,D有点难评了,E优化很妙。

A. Legs

tag:签到

void solve(){
cin >> n;
int a = n / 4, b = n % 4;
a += b / 2;
cout << a << endl;
}

B. Scale

tag:模拟

void solve(){
cin >> n >> k;
vector a(n + 1, vector<char>(n + 1));
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++)
cin >> a[i][j];
for (int i = 1; i <= n; i += k){
for (int j = 1; j <= n; j += k)
cout << a[i][j];
cout << endl;
}
}

C. Sort

tag: 前缀和

Description:给定两个字符串a,b,有q次查询,每次查询给定li,ri。每次操作可以将一个ai变成一个字符x;求每次询问令sort(al,ar)==sort(bl,br)的最小操作次数。

Solution:典型的trick,使用前缀和记录一下每个字符出现的次数,这样我们就可以O(1)得到每个区间内每个字符的个数。

void solve(){
int q;
cin >> n >> q;
string a, b;
cin >> a >> b;
a = "$" + a;
b = "$" + b;
vector ta(n + 1, vector<int>(26));
vector tb(n + 1, vector<int>(26));
for (int i = 1; i <= n; i ++){
ta[i] = ta[i - 1];
tb[i] = tb[i - 1];
ta[i][a[i] - 'a'] ++;
tb[i][b[i] - 'a'] ++;
}
while (q --){
int l, r;
cin >> l >> r;
vector<int> t(26), tt(26);
int cnt = 0;
for (int i = 0; i < 26; i ++){
t[i] = ta[r][i] - ta[l - 1][i];
tt[i] = tb[r][i] - tb[l - 1][i];
cnt += abs(t[i] - tt[i]);
}
cout << cnt / 2 << endl;
}
}

D. Fun

tag:数学

Description:给定n,x,求三元组a,b,c满足ab+ab+bc<=n\anda+b+c<=x的三元组的数量。

Solution:注意到是不等式显然需要化简,我们枚举a,b的值,那么c<=(nab)/(a+b)\andc<=x(a+b)。时间复杂度是一个调和机数,n+n/2+n/3+...+1

void solve(){
int x;
cin >> n >> x;
int ans = 0;
for (int a = 1; a < n; a ++)
for (int b = 1; a * b < n; b ++){
ans += max(0LL, min((n - a * b) / (a + b), x - a - b));
}
cout << ans << endl;
}

E. Decode

tag:前缀和 + 优化

Description:给定一个0,1字符串s,对于所有1<=l<=r<=n,求有多少对x,yl<=x<=y<=r,且[sx,sy]中两种字符的数量相等。

Solution:显然对于一个x,y区间,对所有包含它们的l,r都会有一个贡献,那么总贡献为x(ny+1)

  • 但是对于同一个y可能有多个x,使用vector存储会TLE。
  • 我们考虑同一个y,两个x的贡献:x1(ny+1)+x2(ny+1)==(x1+x2)(ny+1)化简后可知,我们只需要将相同状态的下标和相加即可。
void solve(){
string s;
cin >> s;
s = "&" + s;
map<int, int> mp;
int ans = 0;
int t = 0;
mp[0] = 1;
for (int i = 1; i < s.size(); i ++){
if (s[i] == '1')
t ++;
else
t --;
ans += (s.size() - i) * (mp[t]) % mod;
ans %= mod;
mp[t] += i + 1;
mp[t] %= mod;
}
cout << ans << endl;
}

F. Bomb

tag: 二分

Description:给定两个长度为n的数组,可以执行k次操作,每次操作后ai变为max(0,aibi),得分加ai,求最高得分。1 <= n <= 1e5, 1 <= k <= 1e9

Solution:显然我们需要每次取最大的ai,但是暴力会超时。我们发现每个数都变化是一个等差数列,那么能否知道每个数最后会变为多少呢?

  • 考虑使用二分找到变化后数组中最大值的最小值x(即数组中所有值都不能超过这个值)。
  • 如果操作次数小于k,那么剩下的操作次数一定小于数组中x的数量,否则x可以更小。
void solve(){
cin >> n >> k;
vector<int> a(n), b(n);
for (int i = 0; i < n; i ++)
cin >> a[i];
for (int i = 0; i < n; i ++)
cin >> b[i];
int ans = 0;
auto check = [&](int &mid, int &t, int &res) -> bool{
res = 0, t = 0;
for (int i = 0; i < n; i ++){
if (a[i] <= mid)
continue;
int tt = (a[i] - mid + b[i] - 1) / b[i];
res += tt;
t += (a[i] + a[i] - b[i] *(tt - 1)) * tt / 2;
}
if (res > k)
return true;
return false;
};
int l = -1, r = 1e15, t, res;
while (l + 1 < r){
int mid = l + r >> 1;
if (check(mid, t, res))
l = mid;
else
r = mid;
}
cout << t + (k - res) * r << endl;
}
posted @   Sakura17  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示