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);
		}
	}
}
posted @ 2023-09-25 00:20  chfychin  阅读(53)  评论(0)    收藏  举报