Codeforces Round #820 (Div. 3)
前置废话
今天早上没有比赛安排,所以在 \(Codeforces\) 上VP了一个Div3,到\(E\)切不动了,就来写写收获。
Codeforces Round #820 (Div. 3)
A B 过于水,就不说了
只有 B 数组开小没有 1A
C. Jumping on Tiles
考虑到有一个必须的花费是直接从第一个到最后一个,那么可以将字符数组排个序,在第一个字符与最后一个字符之间的都可以跳到,那么直接按循序跳就行,这也就保证了步数最小。
Code moo~~
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
using namespace std;
#define int long long
#define re register int
#define pc_ putchar(' ')
#define pc_n putchar('\n')
#define Bessie signed
inline int read() {
int A = 0, FL = 1;
char CH = getchar();
while(CH < '0' || CH > '9') FL = CH == '-' ? -1 : 1, CH = getchar();
while(CH >= '0' && CH <= '9') A = (A << 3) + (A << 1) + (CH ^ '0'), CH = getchar();
return A * FL;
}
inline void ot(int x) {
if(x < 0) putchar('-'), x = -x;
if(x >= 10) ot(x / 10); putchar(x % 10 | '0');
}
const int CTR = 2e5 + 7;
int T;
int n;
char b[30], a[CTR];
int dp[CTR];
map<char, int> mp;
bool vis[30];
bool cmp(char x, char y) {
return mp[x] < mp[y];
}
vector<int>G[CTR];
char be, ed;
int l, r, ans;
Bessie main() {
for(re i = 1; i <= 26; ++i) {
b[i] = 'a' + i - 1;
// ot(i), pc_, cout << b[i] << endl;
mp[b[i]] = i;
}
T = read();
while(T--) {
scanf("%s", a + 1);
n = strlen(a + 1);
be = a[1], ed = a[n];
ans = l = r = 0;
for(re i = 1; i <= 26; ++i) G[i].clear(), vis[i] = 0;
for(re i = 1; i <= n; ++i) {
G[mp[a[i]]].push_back(i);
}
sort(a + 1, a + n + 1, cmp);
if(be <= ed) {
for(re i = 1; i <= n; ++i) { if(a[i] == be && l == 0) { l = i; break; } }
for(re i = n; i >= 1; --i) { if(a[i] == ed && r == 0) { r = i; break; } }
for(re i = l; i <= r; ++i) {
if(vis[mp[a[i]]]) continue;
vis[mp[a[i]]] = 1;
if(a[i] != a[i - 1] && i != l) ans += mp[a[i]] - mp[a[i - 1]];
}
ot(ans),pc_,ot(r - l + 1),pc_n;
for(re i = 1; i <= 26; ++i) vis[i] = 0;
for(re i = l; i <= r; ++i) {
if(vis[mp[a[i]]]) continue;
vis[mp[a[i]]] = 1;
if(a[i] != a[i - 1] && i != l) ans += mp[a[i]] - mp[a[i - 1]];
for(auto it : G[mp[a[i]]]) {
ot(it),pc_;
}
}
pc_n;
}
if(be > ed) {
for(re i = 1; i <= n; ++i) { if(a[i] == ed && r == 0) { r = i; break; } }
for(re i = n; i >= 1; --i) { if(a[i] == be && l == 0) { l = i; break; } }
for(re i = l; i >= r; --i) {
if(vis[mp[a[i]]]) continue;
vis[mp[a[i]]] = 1;
if(a[i] != a[i + 1] && i != l) ans += mp[a[i + 1]] - mp[a[i]];
}
ot(ans),pc_,ot(l - r + 1),pc_n;
for(re i = 1; i <= 26; ++i) vis[i] = 0;
for(re i = l; i >= r; --i) {
if(vis[mp[a[i]]]) continue;
vis[mp[a[i]]] = 1;
for(auto it : G[mp[a[i]]]) {
ot(it),pc_;
}
}
pc_n;
}
}
return 0;
}
D. Friends and the Restaurant
这题还是卡我挺长时间的。首先转化一下题意:设\(a_i = y_i - x_i\),选出的集合为\(S\)。
那么每次就是让\(\sum_{i \in S} a_i \ge 0\)。题目让选的次数尽量多,可以贪心的每次只选两个。
所以将\(a_i\)排好序,双指针扫一遍就可以了。
我原来还想用STL搞,后来重构时才想到这个解法。
Code moo~~
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
#include <set>
using namespace std;
#define int long long
#define re register int
#define pc_ putchar(' ')
#define pc_n putchar('\n')
#define Bessie signed
inline int read() {
int A = 0, FL = 1;
char CH = getchar();
while(CH < '0' || CH > '9') FL = CH == '-' ? -1 : 1, CH = getchar();
while(CH >= '0' && CH <= '9') A = (A << 3) + (A << 1) + (CH ^ '0'), CH = getchar();
return A * FL;
}
inline void ot(int x) {
if(x < 0) putchar('-'), x = -x;
if(x >= 10) ot(x / 10); putchar(x % 10 | '0');
}
const int CTR = 2e5 + 7, INF = 0x7f7f7f7f;
int T;
int n;
int a[CTR], ans;
bool cmp(int x, int y) { return x > y; }
int l, r;
Bessie main() {
T = read();
while(T--) {
n = read();
ans = 0;
l = 1, r = n;
for(re i = 1; i <= n; ++i) a[i] = read();
for(re i = 1, y; i <= n; ++i) {
y = read();
a[i] = y - a[i];
}
sort(a + 1, a + n + 1, cmp);
// for(re i = 1; i <= n; ++i) ot(a[i]),pc_;
// pc_n;
while(l <= r) {
while(l < r && a[l] + a[r] < 0) r--;
if(l == r) break;
ans++;
// ot(l),pc_,ot(r),pc_n;
l++;
r--;
}
ot(ans),pc_n;
}
return 0;
}
后置废话
下午还想再来一场。