2023河南萌新联赛第(二)场
A. 自动收小麦机(循环并查集)

输入样例1
4 1 2
1 1 4 5
2 2 2 3
4
输出样例1
10
说明
在第4格放出水流后,水流会流向第3格,由于第3格高度比第4格低,所以水流继续向左流向第2格,因为平地水流只能流2格,所以到达第2格后水流停止,收获的小麦数量为1 + 4 + 5 = 10
输入2
5 2 2
1 1 4 5 1
2 2 3 3 4
4
3
输出2
9
6
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N], f[N], c[N];
int n, q, k, m, x, y, t;
unordered_map<int, int> mp;
int check(int x)
{
int t = x, y = b[x];
while(t)
{
t -= k;
if(y != b[t])
{
t = mp[b[t]];
y = b[t];
}
else break;
}
return max(t, 1ll);
}
void solve()
{
cin >> n >> q >> k;
for(int i = 1; i <= n; i ++)
{
cin >> a[i];
f[i] = f[i - 1] + a[i];
}
for(int i = 1; i <= n; i ++)
cin >> b[i], mp[b[i]] = i;
k --;
while(q --)
{
cin >> m;
x = check(m);
cout << f[m] - f[x - 1] << "\n";
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
while(T --)
solve();
return T ^ T;
}
C. 悲伤的RT(RMQ+线性dp,滑动窗口)

输入
5 2
3 1 5 7 9
输出
8
说明
RT可以将前三个树枝放在一个马车上,第四和第五个树枝放在另一个马车上。从第一个马车只能取出攻击力为1的树枝,第二个马车只能取出攻击力为7的树枝。取出树枝的攻击力之和最大为8。
点击查看代码RMQ
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
long long dp[N];
int f[N][32];
int n, c;
void RMQ()
{
for(int j = 0; j < 25; j ++)
{
for(int i = 1; i + (1 << j) - 1 <= n; i ++)
if(!j) f[i][j] = a[i];
else f[i][j] = min(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
}
}
int query(int l, int r)
{
int len = r - l + 1;
int k = log(len) / log(2);
return min(f[l][k], f[r - (1 << k) + 1][k]);
}
int main()
{
cin >> n >> c;
for(int i = 1; i <= n; i ++) cin >> a[i];
RMQ();
for(int i = c; i <= n; i ++)
{
dp[i] = dp[i - 1];
dp[i] = max(dp[i], dp[i - c] + query(i - c + 1, i));
}
long long res = 0;
for(int i = c; i <= n; i ++) res = max(res, dp[i]);
cout << res << '\n';
return 0;
}
点击查看代码 滑动窗口
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10;
int a[N], s[N], q[N], f[N];
int n, k,hh, tt;
void solve()
{
cin >> n >> k;
for(int i = 1; i <= n; i ++)
cin >> a[i], s[i] = s[i - 1] + a[i];
for(int i = 1; i <= n; i ++)
{
f[i] = f[i - 1] + a[i];
while(hh <= tt&&a[q[tt]] >= a[i]) tt --;
q[++ tt] = i;
while(hh <= tt&&q[hh] <= i - k) hh ++;
if(i >= k)
f[i] = min(f[i], f[i - k] + s[i] - s[i - k] - a[q[hh]]);
}
cout << s[n] - f[n] << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
while(T --)
solve();
return T ^ T;
}
E. 释怀的RT(差分+前缀和)

输入1
5
0 1 0 0 10
输出1
4
说明
前四个方格被最后一个心岩照亮
输入2
5
0 1 0 0 1
输出2
3
说明
第一个方格和第三个方格被第二个格子的心岩照亮,第四个方格被第五个格子的心岩照亮,一共有三个格子被照亮
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10;
int a[N], b[N], c[N], n, m, ans, l, r, ll, rr;
struct node
{
int l, r, id;
}p[N], t;
bool bk[N];
int cmp(node a, node b)
{
return a.l < b.l;
}
void solve()
{
cin >> n;
l = 0, r = 0, ll = 0, rr = 0;
int cnt = 0;
for(int i = 1; i <= n; i ++)
{
cin >> a[i];
if(a[i])
{
r = i - 1;
l = max(1ll, i - a[i]);
b[l] ++;
b[r + 1] --;
l = i + 1;
r = min(n, a[i] + i);
b[l] ++;
b[r + 1] --;
}
}
for(int i = 1; i <= n; i ++)
b[i] += b[i - 1], ans += !!b[i];
cout << ans << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
while(T --)
solve();
return T ^ T;
}
G. 爬山(二分)

输入1
3 230
100 200 300
输出1
192
输入2
3 900
150 150 125
输出2
-1
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N], ans;
int p, n, sum, s;
bool check(int x)
{
int sum = 0;
for(int i = 1; i <= n; i ++)
{
if(a[i] > x)
sum += (a[i] - x);
}
// cout << sum << ' ' << x << "\n";
if(sum >= p) return true;
return false;
}
void solve()
{
cin >> n >> p;
for(int i = 1; i <= n; i ++)
cin >> a[i];
for(int i = 1; i <= n; i ++)
sum += a[i];
if(sum * 2 < p)
ans = -1;
else{
sort(a + 1, a + n + 1);
int l = 0, r = sum;
p = (p + 1) >> 1;
while(l < r)
{
int m = l + r >> 1;
if(check(m)) l = m + 1;
else r = m;
}
ans = r - 1;
}
cout << ans << "\n";
}
signed main()
{
/*3 400
100 100 100
cout << 67 * 6 << endl;*/
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;;
while(T --)
solve();
return T ^ T;
}
K. 卡特兰数(质因数分解)

输入
8
输出
2
说明
前8项卡特兰数之积为476150875200,末尾有两个连续的0
点击查看代码
#include<iostream>
using namespace std;
const int N = 5e6 + 10;
int f2[N], f5[N];
int f(int x, int y)
{
int ans = 0;
while(x % y == 0)
{
x /= y;
ans ++;
}
return ans;
}
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
{
f2[i] = f2[i - 1];
f5[i] = f5[i - 1];
f2[i] += f(i * 4 - 2, 2);
f5[i] += f(i * 4 - 2, 5);
f2[i] -= f(i + 1, 2);
f5[i] -= f(i + 1, 5);
}
for(int i = 1; i <= n; i ++)
{
f2[i] += f2[i - 1];
f5[i] += f5[i - 1];
}
// cout << f2[n] << ' ' << f5[n] << ' ';
cout << f5[n] << "\n";
return 0;
}
L. 最长连续相同字符(字符线段树)

输入
10 3
aabbbccdde
1 1 5
2 3 a
1 1 5
输出
3 5
1 3
点击查看代码1
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
struct oper
{
int l, r, len;
char ch;
};
struct node
{
int l, r;
oper maxl, maxr, maxn;
}tr[N << 2];
int n, m;
string s;
oper max(oper &a, oper &b)
{
if(a.len == b.len) return a.l < b.l ? a : b;
return a.len > b.len ? a : b;
}
void pushup(node &u, node &l, node &r)
{
u.maxl = l.maxl;
if(l.maxl.r == l.r&&l.maxl.ch == r.maxl.ch)
u.maxl = {l.maxl.l, r.maxl.r, r.maxl.r - l.maxl.l + 1, l.maxl.ch};
u.maxr = r.maxr;
if(r.maxr.l == r.l&&r.maxr.ch == l.maxr.ch)
u.maxr = {l.maxr.l, r.maxr.r, r.maxr.r - l.maxr.l + 1, r.maxr.ch};
u.maxn = max(l.maxn, r.maxn);
if(l.maxr.ch == r.maxl.ch)
{
oper t = {l.maxr.l, r.maxl.r, r.maxl.r - l.maxr.l + 1, l.maxr.ch};
u.maxn= max(u.maxn, t);
}
}
void pushup(int u)
{
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int u, int l, int r)
{
if(l == r)
tr[u] = {l, r, {l, r, 1, s[l]}, {l, r, 1, s[l]}, {l, r, 1, s[l]}};
else
{
tr[u] = {l, r};
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
void modify(int u, int x, char ch)
{
if(tr[u].l == x&&tr[u].r == x)
tr[u] = {x, x, {x, x, 1, ch}, {x, x, 1, ch}, {x, x, 1, ch}};
else
{
int mid = tr[u].l + tr[u].r >> 1;
if(x <= mid) modify(u << 1, x, ch);
else modify(u << 1 | 1, x, ch);
pushup(u);
}
}
node query(int u, int l, int r)
{
if(tr[u].l >= l&&tr[u].r <= r) return tr[u];
int mid = tr[u].l + tr[u].r >> 1;
if(r <= mid) return query(u << 1, l, r);
if(l > mid) return query(u << 1 | 1, l, r);
node ans, le = query(u << 1, l, r), ri = query(u << 1 | 1, l, r);
pushup(ans, le, ri);
// pushup(ans, query(u << 1, l, r), query(u << 1 | 1, l, r));
// pushup(ans, query(u << 1, l, r), query(u << 1 | 1, l, r));
return ans;
}
void solve()
{
cin >> n >> m >> s;
s = " " + s;
build(1, 1, n);
while(m --)
{
int op;
cin >> op;
if(op == 1)
{
int l, r;
cin >> l >> r;
node ans = query(1, l, r);
cout << ans.maxn.l << ' ' << ans.maxn.r << endl;
}
else
{
int x;
char ch;
cin >> x >> ch;
modify(1, x, ch);
}
}
}
int main()
{
int T = 1;
while(T --)
solve();
return T ^ T;
}
点击查看代码2
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
char s[N];
struct nod
{
int l, r, len;
char c;
};
struct node
{
int l, r;
nod lmax, rmax, tmax;
}tr[N * 4];
nod max(nod &a, nod &b)
{
if(a.len == b.len) return a.l < b.l ? a : b;
return a.len < b.len ? b : a;
}
void pushup(node &u, node &l, node &r)
{
u.lmax = l.lmax;
if(l.lmax.r == l.r && l.lmax.c == r.lmax.c)
{
u.lmax = {l.lmax.l, r.lmax.r, r.lmax.r - l.lmax.l + 1, l.lmax.c};
}
u.rmax = r.rmax;
if(r.rmax.l == r.l && r.rmax.c == l.rmax.c)
{
u.rmax = {l.rmax.l, r.rmax.r, r.rmax.r - l.rmax.l + 1, r.rmax.c};
}
u.tmax = max(l.tmax, r.tmax);
if(l.rmax.c == r.lmax.c)
{
nod t = {l.rmax.l, r.lmax.r, r.lmax.r - l.rmax.l + 1, l.rmax.c};
u.tmax = max(u.tmax, t);
}
}
void pushup(int u)
{
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int u, int l, int r)
{
if(l == r) tr[u] = {l, r, {l, r, 1, s[r]}, {l, r, 1, s[r]}, {l, r, 1, s[r]}};
else
{
tr[u] = {l, r};
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
void modify(int u, int x, char c)
{
if(tr[u].l == x && tr[u].r == x)
{
tr[u].lmax.c = tr[u].rmax.c = tr[u].tmax.c = c;
}
else
{
int mid = tr[u].l + tr[u].r >> 1;
if(x <= mid) modify(u << 1, x, c);
else modify(u << 1 | 1, x, c);
pushup(u);
}
}
node query(int u, int l, int r)
{
if(tr[u].l >= l && tr[u].r <= r) return tr[u];
else
{
int mid = tr[u].l + tr[u].r >> 1;
if(r <= mid) return query(u << 1, l, r);
if(l > mid) return query(u << 1 | 1, l, r);
node res;
node left = query(u << 1, l, r);
node right = query(u << 1 | 1, l, r);
pushup(res, left, right);
return res;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
cin >> s + 1;
build(1, 1, n);
while(m --)
{
int op;
cin >> op;
if(op == 1)
{
int l, r;
cin >> l >> r;
node t = query(1, l, r);
cout << t.tmax.l << ' ' << t.tmax.r << '\n';
}
else
{
int x;
cin >> x;
char c;
cin >> c;
modify(1, x, c);
}
}
}

浙公网安备 33010602011771号