Codeforces Raif Round 1 (Div. 1 + Div. 2)题解
A.Box is Pull
题解:推箱子,特判同行同列即可,$O(1)$
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define rev(i,a,b) for(int i = a; i >= b; i--)
using namespace std;
int x1, y, x2, y2, sum1, sum2, sum;
void solve() {
cin >> x1 >> y >> x2 >> y2;
if(x1 == x2) cout << abs(y2-y) << endl;
else if(y == y2) cout << abs(x2-x1) << endl;
else cout << 2 + abs(y2-y) + abs(x2-x1) << endl;
}
int main() {
int T; cin >> T;
while(T--) solve();
return 0;
}
B.Belted Rooms
题解:看传送带是否能到达最左端或最右端,$O(n)$
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define rev(i,a,b) for(int i = a; i >= b; i--)
using namespace std;
int n, sum;
bool q[300011], h[300011]; //q[i]=(右)能否从1到i, h[i]=(右)能否从i到 n
bool qq[300011], hh[300011];
char a[300011];
void solve() {
cin >> n; sum = 0;
for(int i = 1; i <= n; i++) scanf(" %c", &a[i]);
q[1] = 1;
for(int i = 2; i <= n; i++)
if((a[i-1] == '>' || a[i-1] == '-') && q[i-1] == 1) q[i] = 1;
else q[i] = 0;
h[n] = 1;
for(int i = n-1; i >= 1; i--)
if((a[i] == '>' || a[i] == '-') && h[i+1] == 1) h[i] = 1;
else h[i] = 0;
qq[1] = 1;
for(int i = 2; i <= n; i++)
if((a[i-1] == '<' || a[i-1] == '-') && qq[i-1] == 1) qq[i] = 1;
else qq[i] = 0;
hh[n] = 1;
for(int i = n-1; i >= 1; i--)
if((a[i] == '<' || a[i] == '-') && hh[i+1] == 1) hh[i] = 1;
else hh[i] = 0;
for(int i = 1; i <= n; i++) {
int las = i - 1, nxt = i + 1;
if(las == 0) las = n;
if(nxt > n) nxt = 1;
if(a[i] == '-' || a[las] == '-') sum++;
else {
if(a[n] == '>' || a[n] == '-') {
if(q[i] == 1 && h[i] == 1) {
sum++; continue;
}
}
if(a[n] == '<' || a[n] == '-') {
if(qq[i] == 1 && hh[i] == 1) sum++;
}
}
}
cout << sum << endl;
}
int main() {
int T; cin >> T;
while(T--) solve();
return 0;
}
C.ABBB
题解:我们分类讨论一下,发现消掉任意一个都是最优的,于是直接暴力,我写了个双向链表,$O(n)$
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define rev(i,a,b) for(int i = a; i >= b; i--)
using namespace std;
string s;
int n, pre[200011], nxt[200011], ans;
void solve() {
cin >> s; n = s.size(); ans = n;
nxt[0] = 1;
for(int i = 1; i < n; i++) {
pre[i] = i-1;
nxt[i] = i+1;
}
pre[0] = n;
for(int i = 0; i < n; i = i) {
if(s[i] == 'A' && s[nxt[i]] == 'B') {
ans -= 2;
nxt[pre[i]] = nxt[nxt[i]];
pre[nxt[nxt[i]]] = pre[i];
s[i] = s[nxt[i]] = ' ';
if(pre[i] != n) i = pre[i];
else i = nxt[nxt[i]];
continue;
}
if(s[i] == 'B' && s[nxt[i]] == 'B') {
ans -= 2;
nxt[pre[i]] = nxt[nxt[i]];
pre[nxt[nxt[i]]] = pre[i];
s[i] = s[nxt[i]] = ' ';
if(pre[i] != n) i = pre[i];
else i = nxt[nxt[i]];
continue;
}
i = nxt[i];
}
cout << ans << endl;
}
int main() {
int T; cin >> T;
while(T--) solve();
return 0;
}
E.Carrots for Rabbits
题解:我们考虑用堆维护贪心,每次把切后收益最大的拿来切,注意这里的收益是原长度/段数,不是切后的长度/段数,$O(n \log n)$
#include <cstdio>
#include <queue>
#include <iostream>
#define ll long long
#define mkp make_pair
#define fr first
#define se second
using namespace std;
int n, k, a[1000011];
ll ans;
priority_queue <pair<ll, pair<int, int> > > q;
ll cal(int s1, int s2) {
ll s = s1 % s2, p = s1 / s2;
return (s2 - s) * p * p + s * (p+1) * (p+1);
}
int main() {
scanf("%d%d", &n, &k); k -= n;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
ans += (ll)a[i] * (ll)a[i];
q.push(mkp(cal(a[i], 1) - cal(a[i], 2), mkp(a[i], 1)));
}
for(int i = 1; i <= k; i++) {
int sum = q.top().se.fr, num = q.top().se.se;
ans -= q.top().fr;
q.pop();
q.push(mkp(cal(sum, num+1) - cal(sum, num+2), mkp(sum, num+1)));
}
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号