Codeforces Round #625 (Div.2, based on Technocup 2020 Final Round)

比赛链接

A. Contest for Robots

Solution

$b$ 能赢的题设为 $1$ 分即可。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<algorithm>
#include<cstdio>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

const int N = 105;

int n, a[N], b[N], cnta, cntb;

int main(){
read(n);
for(int i = 1; i <= n; i++) read(a[i]);
for(int i = 1; i <= n; i++) read(b[i]);
for(int i = 1; i <= n; i++){
if(a[i] == 1 && b[i] == 0) cnta++;
if(a[i] == 0 && b[i] == 1) cntb++;
}
if(cnta == 0){
puts("-1");
return 0;
}
int ans = cntb / cnta;
if(cnta * ans <= cntb) ans++;
printf("%d\n", ans);
return 0;
}

B. Journey Planning

Solution

题目中 $c_{i+1}-c_i=b_{c_{i+1}}-b_{c_i}$ 可以改写为:$b_{c_{i+1}}-c_{i+1}=b_{c_i}-c_i$. 于是计算(值减下标)相同的那些数的值之和的最大值即可。

坑点:减去下标后会出现负数。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<algorithm>
#include<cstdio>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;

int n;
LL b, ans, cnt[800005];

int main(){
read(n);
for(int i = 1; i <= n; i++){
read(b);
cnt[b - i + 200000] += b;
ans = max(ans, cnt[b - i + 200000]);
}
printf("%lld\n", ans);
return 0;
}

C. Remove Adjacent

Solution

从 $z$ 到 $a$ 枚举要删的字符,把字符串中能删的该字符都删掉即可。为代码方便,实践中我们把要删的字符减一,等价于删掉该字符再并到一起。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<algorithm>
#include<cstdio>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;

const int N = 105;

int n, ans;
bool b[N];
char s[N];

int main(){
read(n);
scanf("%s", s+1);
for(char ch = 'z'; ch >= 'a'; ch--){
for(int i = 2; i <= n; i++)
if(s[i] == ch && s[i-1] == ch - 1)
b[i] = true, s[i] = ch - 1;
for(int i = n - 1; i >= 1; i--)
if(s[i] == ch && s[i+1] == ch - 1)
b[i] = true, s[i] = ch - 1;
}
for(int i = 1; i <= n; i++) ans += b[i];
printf("%d\n", ans);
return 0;
}

D. Navigation System

Solution

倒着建边,能用 $bfs$ 求出每个点到终点的最短距离以及走最短距离时下一步能走哪些节点。依次访问实际路径的节点:求最少次数时,如果下一步能走的节点中没有实际上下一步走的节点,答案加一;求最多次数时,如果下一步能走的节点中有不是实际上下一步走的节点,答案加一。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;

const int N = 200005;

int n, m, u, v, k, p[N], s, t, maxans, minans;
bool has[N];

struct Edge{
int nxt, to;
}edge[N];
int head[N], edgeNum;
void addEdge(int from, int to){
edge[++edgeNum] = (Edge){head[from], to};
head[from] = edgeNum;
}

int dis[N], cnt[N], nxt[N];
void bfs(){
memset(dis, 0x7f, sizeof dis);
queue<int> q;
dis[t] = 0;
q.push(t);
while(!q.empty()){
int cur = q.front(); q.pop();
for(int i = head[cur]; i; i = edge[i].nxt){
if(dis[edge[i].to] > dis[cur] + 1){
dis[edge[i].to] = dis[cur] + 1;
cnt[edge[i].to] = (cur != nxt[edge[i].to]);
if(cur == nxt[edge[i].to]) has[edge[i].to] = true;
q.push(edge[i].to);
}
else if(dis[edge[i].to] == dis[cur] + 1){
cnt[edge[i].to] += (cur != nxt[edge[i].to]);
if(cur == nxt[edge[i].to]) has[edge[i].to] = true;
}
}
}
}

int main(){
read(n, m);
for(int i = 1; i <= m; i++){
read(u, v);
addEdge(v, u);
}
read(k);
for(int i = 1; i <= k; i++){
read(p[i]);
if(i > 1) nxt[p[i-1]] = p[i];
}
s = p[1], t = p[k];
bfs();
for(int i = 1; i < k; i++) maxans += (cnt[p[i]] > 0);
for(int i = 1; i < k; i++) minans += (!has[p[i]]);
printf("%d %d\n", minans, maxans);
return 0;
}

E. World of Darkraft: Battle for Azathoth

Solution

武器按照攻击力从小到大排序,怪兽按照防御从小到大排序,则枚举武器时,能用一个指针指出当前能攻击的怪兽集合。以盔甲的防御力为值域建立线段树,维护该防御力能获得的最大利益(能攻击的怪兽价值减去自己的价格)。指针每往后移一次(即把一个怪兽加入被攻击集合),把线段树中大于这个怪兽的攻击力的所有点加上这个怪物的价值,询问线段树中最大价值,减去当前武器的价格就得到了这个武器的最大收益。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include<algorithm>
#include<iostream>
#include<cstdio>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;

const int N = 200005;

int n, m, p, wid, aid;
LL ans = -1e16, fun[1123456];
struct Weapon{
LL att, cost;
bool operator < (const Weapon &A) const{
return att == A.att ? cost < A.cost : att < A.att;
}
}w[N];
struct Armor{
LL def, cost;
bool operator < (const Armor &A) const{
return def == A.def ? cost < A.cost : def < A.def;
}
}a[N];
struct Monster{
LL att, def, cost;
bool operator < (const Monster &A) const{
return def < A.def;
}
}mon[N];

struct segTree{
int l, r;
LL mxc, lazy;
}tr[4123456];
#define lid id<<1
#define rid id<<1|1
#define mid ((tr[id].l + tr[id].r) >> 1)
inline void pushup(int id){
tr[id].mxc = max(tr[lid].mxc, tr[rid].mxc);
}
inline void pushdown(int id){
if(tr[id].l == tr[id].r) return;
if(tr[id].lazy){
tr[lid].lazy += tr[id].lazy;
tr[lid].mxc += tr[id].lazy;
tr[rid].lazy += tr[id].lazy;
tr[rid].mxc += tr[id].lazy;
tr[id].lazy = 0;
}
}
void build(int id, int l, int r){
tr[id].l = l, tr[id].r = r;
if(tr[id].l == tr[id].r){
if(fun[tr[id].l]) tr[id].mxc = -fun[tr[id].l];
else tr[id].mxc = -1e16;
return;
}
build(lid, l, mid);
build(rid, mid+1, r);
pushup(id);
}
void add(int id, int l, int r, int val){
pushdown(id);
if(tr[id].l == l && tr[id].r == r){
tr[id].lazy += val;
tr[id].mxc += val;
return;
}
if(r <= mid) add(lid, l, r, val);
else if(l > mid) add(rid, l, r, val);
else add(lid, l, mid, val), add(rid, mid+1, r, val);
pushup(id);
}
int query(int id, int l, int r){
pushdown(id);
if(tr[id].l == l && tr[id].r == r) return tr[id].mxc;
if(r <= mid) return query(lid, l, r);
else if(l > mid) return query(rid, l, r);
else return max(query(lid, l, mid), query(rid, mid+1, r));
}

int main(){
read(n, m, p);
for(int i = 1; i <= n; i++) read(w[i].att, w[i].cost);
for(int i = 1; i <= m; i++) read(a[i].def, a[i].cost);
for(int i = 1; i <= p; i++) read(mon[i].def, mon[i].att, mon[i].cost);
sort(w+1, w+n+1);
sort(a+1, a+m+1);
sort(mon+1, mon+p+1);
for(int i = 1; i <= n; i++) if(w[i].att != w[i-1].att) w[++wid] = w[i];
for(int i = 1; i <= m; i++) if(a[i].def != a[i-1].def) a[++aid] = a[i];
for(int i = 1; i <= aid; i++) fun[a[i].def] = a[i].cost;
build(1, 1, 1e6+5);
int pt = 0;
for(int i = 1; i <= wid; i++){
while(pt < p && mon[pt+1].def < w[i].att){
pt++;
add(1, mon[pt].att+1, 1e6+5, mon[pt].cost);
}
ans = max(ans, query(1, 1, 1e6+5) - w[i].cost);
}
printf("%lld\n", ans);
return 0;
}

F. Reachable Strings

Solution

两个字符串,只要其 $0$ 的个数与奇偶性相同,就可以互相转化。例如:$0101100$ 和 $0111000$ 都有 $4$ 个零且奇偶性都是奇-奇-偶-奇,所以它们可以互相转化。于是对原字符串针对 $0$ 及其奇偶性进行哈希。例如:忽视 $1$,奇数位的 $0$ 哈希成 $2$,偶数位的 $0$ 哈希成 $1$,这样就可以达到目的。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<cstdio>

using namespace std;

typedef long long LL;

const int N = 200005;
const LL MOD = 998244353;

int n, q, cnt[N];
char t[N];
LL h[2][N], base = 233, power[N] = {1};

inline void Hash(char s[]){
for(int i = 1; i <= n; i++){
if(s[i] == '0'){
h[0][i] = (h[0][i-1] * base + (i & 1) + 1) % MOD;
h[1][i] = (h[1][i-1] * base + (!(i & 1)) + 1) % MOD;
} else h[0][i] = h[0][i-1], h[1][i] = h[1][i-1];
}
}
inline LL getSubstring(int l, int r, int k){
return ((h[k][r] - h[k][l-1] * power[cnt[r] - cnt[l-1]]) % MOD + MOD) % MOD;
}

int main(){
scanf("%d", &n);
scanf("%s", t+1);
for(int i = 1; i <= n; i++){
power[i] = power[i-1] * base % MOD;
cnt[i] = cnt[i-1] + (t[i] == '0');
}
Hash(t);
scanf("%d", &q);
while(q--){
int l1, l2, len; scanf("%d%d%d", &l1, &l2, &len);
LL res1 = getSubstring(l1, l1 + len - 1, l1 & 1);
LL res2 = getSubstring(l2, l2 + len - 1, l2 & 1);
puts(res1 == res2 ? "YES" : "NO");
}
return 0;
}
作者

xyfJASON

发布于

2020-03-02

更新于

2020-12-20

许可协议

评论