Codeforces Round #797 (Div. 3)
作者:互联网
Codeforces Round #797 (Div. 3)
感觉这场div3要简单许多,不过还是没ak···。
ABC略,从D开始吧
D
题意:
给一个“BW” 串,问至少几次修改,能构成一个长度为 \(k\) 的连续的 “B”。
思路:
暴力把 \([1,k]\) 的串操作次数算了,之后向右滑动,只用计算最左边滑出的和最右边新加入的字符产生的贡献就行。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<random>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;
void solve()
{
int n,k; cin >> n >> k;
string s; cin >> s;
s = ' ' + s;
int ans = 0;
rep(i,1,k) if(s[i] == 'W') ans ++;
int res = ans;
rep(i,2,n - k + 1) {
if(s[i - 1] == s[i + k - 1]) continue;
if(s[i - 1] == 'W') ans -= 1;
if(s[i - 1] == 'B') ans += 1;
res = min(ans, res);
}
cout << res << endl;
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--)
solve();
return 0;
}
E
题意:
给一堆数两两配对,每个数对的贡献是 \(\lfloor \frac{a + b}{k} \rfloor\) 。 \(k\) 已知,最大化贡献和
思路:
考虑什么时候更优,发现余数会完全浪费掉,所以明确贪心策略,尽可能让数对的余数为0。场上写的时候没注意,写了一版纯纯的暴力,但竟然能ACΣ(っ °Д °;)っ。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<random>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;
void solve()
{
int n,k; cin >> n >> k;
vector<int> a(n + 1);
rep(i,1,n) cin >> a[i];
set<int> s[k + 1];
rep(i,1,n) s[a[i] % k].insert(i);
int ans = 0;
vector<bool> st(n + 1);
rep(i,1,n) if(!st[i]) {
int x = a[i];
st[i] = 1;
s[x % k].erase(i);
int r1 = k - x % k;
if(s[r1].size()) {
int p = *s[r1].begin();
s[r1].erase(s[r1].begin());
st[p] = 1;
x += a[p];
ans += x / k;
continue;
}
int r = x % k;
int r2 = r;
int mn = inf;
rep(j,0,k - 1) {
if(s[j].size()) {
if((r + j) % k < mn) {
mn = (r + j) % k;
r2 = j;
}
}
}
int p = *s[r2].begin();
s[r2].erase(s[r2].begin());
st[p] = 1;
x += a[p];
ans += x / k;
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--)
solve();
return 0;
}
赛后感觉时间复杂度不太对,又想了想,其实每一个余数为0的数对,都可以对答案有 \(1\) 的额外贡献,其余的余数因为凑不到 \(k\) 被舍去了了,所以匹配一下余数为0就行,这个过程可以对一个余数set二分。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<random>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;
void solve()
{
int n,k; cin >> n >> k;
vector<int> a(n + 1);
rep(i,1,n) cin >> a[i];
multiset<int> s;
int ans = 0;
rep(i,1,n) {
ans += a[i] / k;
s.insert(a[i] % k);
}
while(s.size()) {
int x = *s.begin();
s.erase(s.begin());
auto it = s.lower_bound(k - x);
if(it != s.end()) {
s.erase(it);
ans ++;
}
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--)
solve();
return 0;
}
F
题意:
给一个字符串 \(s\) ,和一个排列 \(p\)。用 \(p\) 对 \(s\) 不断做变换,问至少几次可以重新变成 \(s\) 。
思路
看到是用排列做一些判断,就想到应该是在置换环上做一些事情,可以发现,当每个环中元素不同时,要想重新变回去,就要让所有环在同一时刻回到初始状态,也就是求他们的\(lcm\)。当环中的元素有循环节时,可以发现,这个环回到初始状态的被提前了。
因此对每个环,找循环节,得到贡献,对每个贡献求lcm就行了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<random>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;
void solve()
{
int n; cin >> n;
string s; cin >> s;
vector<int> a(n + 1);
rep(i,1,n) cin >> a[i];
vector<bool> st(n + 1);
s = ' ' + s;
int ans = 1;
rep(i,1,n) if(!st[i]){
string t;
int p = i;
do {
st[p] = 1;
t += s[p];
p = a[p];
}while(!st[p]);
int cnt = 0;
int m = t.size();
rep(j,1,min(m,n)) {
bool ok = 1;
rep(k,0,m - 1) {
if(t[k] != t[(k + j) % m]) {
ok = 0;
break;
}
}
if(ok) {
cnt = j;
break;
}
}
// cout << t << " " << cnt << endl;
ans = lcm(ans, cnt);
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--)
solve();
return 0;
}
G
题意
有很多车厢,每个车厢都有一个最快速度 \(a_i\) ,现在让这些车都向左开,保证在不碰撞的情况下尽可能快。最后速度相同的看成一列列车。
比如 ,\([10,4,5,2,1]\) ,变成 \([10,4,4,2,1]\) ,构成4列列车
共 \(m\) 次询问,每次修改一个 \(a_i := a_i - d\) 。问能构成列车的数量。
思路
首先,发现这个序列中很多值是没有贡献的,有贡献的只有那些能保证单调性的值。也就是跑一遍单调栈,栈中能留下的前缀最小值们。
那么就有一个大概的想法,维护这些前缀最小值,在每次更新时,判断修改值能不能做一个新的前缀最小值。
按照这个想法,我们维护一个前缀最小值的set,当修改后,判断是否会成为一个新的前缀最小值,如果可以,再暴力把后缀中影响单调性的值删除。
时间复杂度,因为set中的值最多 \(n + m\) 种,并且只进行一次删除。所有大概是 \(O(mlog(n + m))\)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<random>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define int long long
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
typedef pair<int,int> PII;
const int MAXN =10 + 2e5 ,mod=1e9 + 7;
void solve()
{
int n,m; cin >> n >> m;
vector<int> a(n + 1);
rep(i,1,n) cin >> a[i];
int limit = a[1];
set<int> s;
s.insert(1);
rep(i,2,n) {
if(limit > a[i]) {
s.insert(i);
limit = a[i];
}
}
rep(i,1,m) {
int pos,x; cin >> pos >> x;
a[pos] -= x;
auto it = s.lower_bound(pos);
if(it != s.begin()) it --;
if(pos > 1 && a[*it] > a[pos]) s.insert(pos);
it = s.upper_bound(pos);
while(it != s.end()) {
if(a[pos] <= a[*it]) it = s.erase(it);
else break;
}
cout << s.size() << " ";
}
cout << endl;
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--)
solve();
return 0;
}
标签:797,int,rep,Codeforces,long,ans,Div,include,define 来源: https://www.cnblogs.com/Mxrush/p/16357097.html