pyyz集训day7

https://files.cnblogs.com/files/blogs/832279/8.13数据结构选讲.zip?t=1786581382&download=true
献上代码:

1.Segment Tree Practice 4

点击查看代码
#include <iostream>
#include <vector>
#define lowbit(x) x & (-x)

using std::cin;
using std::cout;
const int N = 2e5 + 10;
struct Q
{
	int l, r, k, id;
};

int n, q;
int a[N];
int ans[N];
int sum[N];
std::vector<int> pos[N];
std::vector<Q> ope[N];

void add(int x, int k)
{
	for (; x <= n; x += lowbit(x))
		sum[x] += k;
}
int query(int x)
{
	int ret = 0;
	for (; x; x -= lowbit(x))
		ret += sum[x];
	return ret;
}

int main()
{
	cin >> n >> q;
	for (int i = 1; i <= n; ++i)
	{
		cin >> a[i];
		if (!pos[a[i]].size())
			pos[a[i]].push_back(0);
		pos[a[i]].push_back(i);
	}
	for (int i = 1; i <= n; ++i)
	{
		if (pos[i].size())
			pos[i].push_back(n + 1);
	}
	for (int i = 1; i <= n; ++i)
	{
		if (!pos[i].size())
			continue;
		for (int j = 1; j <= (int)pos[i].size() - 2; ++j)
		{
			int l = pos[i][j - 1] + 1;
			int r = pos[i][j + 1] - 1;
			int m = pos[i][j];
			ope[l].push_back({m, r, 1, 0});
			if (m < n)
				ope[m + 1].push_back({m, r, -1, 0});
		}
	}
	for (int i = 1; i <= q; ++i)
	{
		int l, r;
		cin >> l >> r;
		ope[l].push_back({r, 0, 0, i});
	}
	for (int i = 1; i <= n; ++i)
	{
		for (auto it : ope[i])
		{
			if (it.id)
				ans[it.id] = query(it.l);
			else
			{
				add(it.l, it.k);
				if (it.r < n)
					add(it.r + 1, -it.k);
			}
		}
	}
	for (int i = 1; i <= q; ++i)
		cout << ans[i] << '\n';
	return 0;
}

2.k-d-sequence

点击查看代码
#include <iostream>
#include <map>
 
using std::cin;
using std::cout;
const int N = 2e5 + 10;
typedef long long ll;
const ll oo = 1e18;
struct Node
{
	ll mn;
	ll tag;
	Node()
	{
		tag = 0;
		mn = oo;
	}
	friend Node operator+(const Node &l, const Node &r)
	{
		Node ret;
		ret.mn = std::min(l.mn, r.mn);
		return ret;
	}
} z[N << 2];
 
int top;
int top1;
int n, k, d;
int a[N];
int q[N];
int p[N];
int pre[N];
int stv[N];
int stl[N];
int str[N];
int stv1[N];
int stl1[N];
int str1[N];
std::map<int, int> pos;
 
#define root 1, n, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
 
void add(int rt, ll v)
{
	z[rt].mn += v;
	z[rt].tag += v;
}
void push_down(int rt)
{
	if (z[rt].tag)
	{
		add(rt << 1, z[rt].tag);
		add(rt << 1 | 1, z[rt].tag);
		z[rt].tag = 0;
	}
}
void modiadd(int l, int r, int rt, int nowl, int nowr, ll v)
{
	if (nowl <= l && r <= nowr)
	{
		add(rt, v);
		return;
	}
	push_down(rt);
	int mid = (l + r) >> 1;
	if (nowl <= mid)
		modiadd(lson, nowl, nowr, v);
	if (nowr > mid)
		modiadd(rson, nowl, nowr, v);
	z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
int query(int l, int r, int rt, int nowl, int nowr, ll k)
{
	if (nowl > nowr)
		return -1;
	if (nowl <= l && r <= nowr)
	{
		if (z[rt].mn > k)
			return -1;
		if (l == r)
			return l;
		int mid = (l + r) >> 1;
		push_down(rt);
		if (z[rt << 1].mn <= k)
			return query(lson, nowl, nowr, k);
		else
			return query(rson, nowl, nowr, k);
	}
	push_down(rt);
	int mid = (l + r) >> 1;
	int ans = -1;
	if (nowl <= mid)
		ans = query(lson, nowl, nowr, k);
	if (ans == -1 && nowr > mid)
		ans = query(rson, nowl, nowr, k);
	return ans;
}
void build(int l, int r, int rt)
{
	if (l == r)
	{
		z[rt].mn = l - k;
		return;
	}
	int mid = (l + r) >> 1;
	build(lson);
	build(rson);
	z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
Node qdebug(int l, int r, int rt, int nowl, int nowr)
{
	if (nowl <= l && r <= nowr)
		return z[rt];
	int mid = (l + r) >> 1;
	push_down(rt);
	if (nowl <= mid)
	{
		if (nowr > mid)
			return qdebug(lson, nowl, nowr) + qdebug(rson, nowl, nowr);
		else
			return qdebug(lson, nowl, nowr);
	}
	else
		return qdebug(rson, nowl, nowr);
}
 
int main()
{
	cin >> n >> k >> d;
	for (int i = 1; i <= n; ++i)
		cin >> a[i];
	if (!d)
	{
		int ans = 0;
		int al, ar;
		for (int i = 1; i <= n; ++i)
		{
			int j = i - 1;
			while (j < n && a[j + 1] == a[i])
				j++;
			if (ans < j - i + 1)
			{
				ans = j - i + 1;
				al = i, ar = j;
			}
			i = j;
		}
		cout << al << ' ' << ar << '\n';
		return 0;
	}
	for (int i = 1; i <= n; ++i)
		q[i] = (a[i] % d + d) % d, p[i] = (a[i] - q[i]) / d;
	for (int i = 1; i <= n; ++i)
	{
		pre[i] = pos[a[i]];
		pos[a[i]] = i;
	}
	build(root);
	int ans = 0;
	int al, ar;
	for (int i = 1; i <= n; ++i)
	{
		int nl = i, nr = i - 1;
		while (nr < n && q[nr + 1] == q[nl])
			nr++;
		int ql = nl;
		top = 0, top1 = 0;
		for (int j = nl; j <= nr; ++j)
		{
			modiadd(root, nl, nr, (j == nl ? -j : (j - 1) - j));
			while (top && stv[top] <= p[j])
			{
				modiadd(root, stl[top], str[top], -stv[top]);
				top--;
			}
			++top;
			stv[top] = p[j];
			stl[top] = str[top - 1] + 1;
			str[top] = j;
			modiadd(root, stl[top], str[top], stv[top]);
			while (top1 && stv1[top1] >= p[j])
			{
				modiadd(root, stl1[top1], str1[top1], stv1[top1]);
				top1--;
			}
			++top1;
			stv1[top1] = p[j];
			stl1[top1] = str1[top1 - 1] + 1;
			str1[top1] = j;
			modiadd(root, stl1[top1], str1[top1], -stv1[top1]);
			ql = std::max(ql, pre[j] + 1);
			int now = query(root, ql, j, 0);
			if (now != -1)
			{
				if (ans < j - now + 1)
				{
					ans = j - now + 1;
					al = now, ar = j;
				}
			}
		}
		i = nr;
	}
	cout << al << ' ' << ar << '\n';
	return 0;
}

3.A. 数据结构

点击查看代码
#include <iostream>
#include <vector>
#define lowbit(x) x & (-x)

using std::cin;
using std::cout;
const int N = 1e6 + 10;
struct Node
{
	int l, r;
	int k;
	int id;
};

int n, m;
int l[N];
int r[N];
int a[N];
int ans[N];
int sum[N];
int cnt[N];
std::vector<int> num;
std::vector<int> pos[N];
std::vector<Node> ope[N];

void add(int x, int k)
{
	for (; x <= n; x += lowbit(x))
		sum[x] += k;
}
int query(int x)
{
	int ret = 0;
	for (; x; x -= lowbit(x))
		ret += sum[x];
	return ret;
}

int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
	{
		cin >> a[i];
		cnt[a[i]]++;
		if (cnt[a[i]] == 1)
			pos[a[i]].push_back(0);
		pos[a[i]].push_back(i);
		if (!l[a[i]])
			l[a[i]] = i;
		r[a[i]] = i;
	}
	for (int i = 1; i <= n; ++i)
	{
		if (cnt[i])
		{
			pos[i].push_back(n + 1);
			num.push_back(i);
			if (!cnt[i + 1])
				num.push_back(i + 1);
		}
	}
	for (auto it : num)
	{
		if (!cnt[it])
		{
			for (int i = 1; i < (int)pos[it - 1].size(); ++i)
			{
				int x = pos[it - 1][i - 1] + 1;
				int y = pos[it - 1][i] - 1;
				if (x <= y)
				{
					ope[x].push_back({x, y, 1, 0});
					if (y < n)
						ope[y + 1].push_back({x, y, -1, 0});
				}
			}
		}
		else if (!cnt[it - 1])
		{
			int x = l[it];
			int y = r[it];
			if (x >= 1 && y <= n)
			{
				ope[1].push_back({y, n, 1, 0});
				if (x < n)
					ope[x + 1].push_back({y, n, -1, 0});
			}
		}
		else
		{
			int x = l[it];
			int y = r[it];
			for (int i = 1; i < (int)pos[it - 1].size(); ++i)
			{
				int a = pos[it - 1][i - 1] + 1;
				int b = pos[it - 1][i] - 1;
				if (a <= x && y <= b)
				{
					ope[a].push_back({y, b, 1, 0});
					if (x < n)
						ope[x + 1].push_back({y, b, -1, 0});
				}
			}
		}
	}
	for (int i = 1; i <= m; ++i)
	{
		int l, r;
		cin >> l >> r;
		ope[l].push_back({r, 0, 0, i});
	}
	for (int i = 1; i <= n; ++i)
	{
		for (auto it : ope[i])
		{
			if (it.id)
				ans[it.id] = query(it.l);
			else
			{
				add(it.l, it.k);
				if (it.r < n)
					add(it.r + 1, -it.k);
			}
		}
	}
	for (int i = 1; i <= m; ++i)
		cout << num.size() - ans[i] << '\n';
	return 0;
}

4.rldcot

点击查看代码
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#define pii std::pair<int, int>
#define lowbit(x) x & (-x)

using std::cin;
using std::cout;
const int N = 1e5 + 10;
typedef long long ll;
struct Mod
{
	int l, r, id;
	bool q;
};

int n, m;
int top;
int id[N];
int sum[N];
int ans[N * 5];
pii stk[N];
ll dist[N];
std::vector<ll> vec;
std::set<int> s[N];
std::vector<pii> e[N];
std::vector<pii> pr[N];
std::vector<Mod> modi[N];

void dfs(int x, int fa)
{
	for (auto nxt : e[x])
	{
		int to = nxt.first;
		if (to == fa)
			continue;
		int val = nxt.second;
		dist[to] = dist[x] + val;
		dfs(to, x);
	}
}
void dfs2(int x, int fa)
{
	for (auto nxt : e[x])
	{
		int to = nxt.first;
		if (to != fa)
			dfs2(to, x);
	}
	s[x].insert(x);
	pr[dist[x]].push_back({x, x});
	id[x] = x;
	for (auto nxt : e[x])
	{
		int to = nxt.first;
		if (to != fa)
		{
			if (s[id[x]].size() < s[id[to]].size())
				std::swap(id[x], id[to]);
			for (auto it : s[id[to]])
			{
				auto a = s[id[x]].lower_bound(it);
				if (a != s[id[x]].end())
					pr[dist[x]].push_back({std::min(it, *a), std::max(it, *a)});
				if (a != s[id[x]].begin())
				{
					auto b = std::prev(a);
					pr[dist[x]].push_back({std::min(it, *b), std::max(it, *b)});
				}
			}
			for (auto it : s[id[to]])
				s[id[x]].insert(it);
		}
	}
}
void add(int x, int k)
{
	for (; x <= n; x += lowbit(x))
		sum[x] += k;
}
int query(int x)
{
	int ret = 0;
	for (; x; x -= lowbit(x))
		ret += sum[x];
	return ret;
}

int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n >> m;
	for (int i = 1; i < n; ++i)
	{
		int u, v, d;
		cin >> u >> v >> d;
		e[u].push_back({v, d});
		e[v].push_back({u, d});
	}
	dfs(1, 0);
	for (int i = 1; i <= n; ++i)
		vec.push_back(dist[i]);
	std::sort(vec.begin(), vec.end());
	vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
	int tot = vec.size();
	for (int i = 1; i <= n; ++i)
		dist[i] = std::lower_bound(vec.begin(), vec.end(), dist[i]) - vec.begin() + 1;
	dfs2(1, 0);
	for (int i = 1; i <= tot; ++i)
	{
		std::sort(pr[i].begin(), pr[i].end());
		int top = 0;
		for (auto it : pr[i])
		{
			int x = it.first;
			int y = it.second;
			if (top && stk[top].first == x)
				continue;
			while (top && stk[top].second >= y)
				top--;
			stk[++top] = it;
		}
		stk[0] = {0, 0};
		for (int i = 1; i <= top; ++i)
			modi[stk[i].second].push_back({stk[i - 1].first + 1, stk[i].first, 0, false});
	}
	for (int i = 1; i <= m; ++i)
	{
		int l, r;
		cin >> l >> r;
		modi[r].push_back({l, 0, i, true});
	}
	for (int i = 1; i <= n; ++i)
	{
		for (auto it : modi[i])
		{
			if (!it.q)
			{
				add(it.l, 1);
				if (it.r < n)
					add(it.r + 1, -1);
			}
			else
				ans[it.id] = query(it.l);
		}
	}
	for (int i = 1; i <= m; ++i)
		cout << ans[i] << '\n';
	return 0;
}

ps:这道题卡线段树,请用树状数组。

5.フードコート (Day1)

点击查看代码
#include <iostream>
#include <vector>
#define int long long

using std::cin;
using std::cout;
const int N = 2.5e5 + 10;
struct Mod
{
	int t, v, c;
	int q;
};
struct Node
{
	int sum1;
	int id;
	int sum2;
	int min;
	int p;
	friend Node operator+(const Node &l, const Node &r)
	{
		Node ret;
		ret.sum1 = l.sum1 + r.sum1;
		ret.sum2 = l.sum2 + r.sum2;
		if (l.min <= l.sum2 + r.min)
			ret.min = l.min, ret.p = l.p;
		else
			ret.min = l.sum2 + r.min, ret.p = r.p;
		return ret;
	}
} z[N << 2];

int S;
bool qr[N];
int ans[N];
std::vector<Mod> mod[N];

#define root 1, q, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1

void modicov(int l, int r, int rt, int p, int id, int k)
{
	if (l == r)
	{
		if (k >= 0)
			z[rt].sum1 = k;
		else
			z[rt].sum1 = 0;
		z[rt].sum2 = z[rt].min = k;
		z[rt].id = id;
		z[rt].p = l;
		return;
	}
	int mid = (l + r) >> 1;
	if (p <= mid)
		modicov(lson, p, id, k);
	else
		modicov(rson, p, id, k);
	z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
Node query(int l, int r, int rt, int nowl, int nowr)
{
	if (nowl <= l && r <= nowr)
		return z[rt];
	int mid = (l + r) >> 1;
	if (nowl <= mid)
	{
		if (nowr > mid)
			return query(lson, nowl, nowr) + query(rson, nowl, nowr);
		else
			return query(lson, nowl, nowr);
	}
	else
		return query(rson, nowl, nowr);
}
int qp(int l, int r, int rt, int nowl, int nowr, int k)
{
	if (nowl <= l && r <= nowr)
	{
		if (z[rt].sum1 + S < k)
			return S += z[rt].sum1, -1;
		if (l == r)
			return z[rt].id;
		int mid = (l + r) >> 1;
		if (S + z[rt << 1 | 1].sum1 >= k)
			return qp(rson, nowl, nowr, k);
		else
			return S += z[rt << 1 | 1].sum1, qp(lson, nowl, nowr, k);
	}
	int mid = (l + r) >> 1;
	int ans = -1;
	if (nowr > mid)
		ans = qp(rson, nowl, nowr, k);
	if (ans == -1 && nowl <= mid)
		ans = qp(lson, nowl, nowr, k);
	return ans;
}

signed main()
{
	int n, m, q;
	cin >> n >> m >> q;
	for (int i = 1; i <= q; ++i)
	{
		int t;
		cin >> t;
		if (t == 1)
		{
			int l, r, c, k;
			cin >> l >> r >> c >> k;
			mod[l].push_back({i, c, k, 0});
			if (r < n)
				mod[r + 1].push_back({i, 0, 0, 1});
		}
		else if (t == 2)
		{
			int l, r, k;
			cin >> l >> r >> k;
			mod[l].push_back({i, 0, -k, 2});
			if (r < n)
				mod[r + 1].push_back({i, 0, 0, 3});
		}
		else
		{
			qr[i] = true;
			int a, b;
			cin >> a >> b;
			mod[a].push_back({i, 0, b, 4});
		}
	}
	for (int i = 1; i <= n; ++i)
	{
		for (auto it : mod[i])
		{
			if (it.q <= 3)
				modicov(root, it.t, it.v, it.c);
			else
			{
				S = 0;
				int mnp = query(root, 1, it.t).p;
				int beg;
				if (mnp == 0 || query(root, 1, mnp).sum2 >= 0)
					beg = 1;
				else
					beg = mnp + 1;
				int sm = query(root, beg, it.t).sum2;
				if (sm < it.c)
					ans[it.t] = 0;
				else
					ans[it.t] = qp(root, beg, it.t, sm - it.c + 1);
			}
		}
	}
	for (int i = 1; i <= q; ++i)
	{
		if (qr[i])
			cout << ans[i] << '\n';
	}
	return 0;
}

6.火车管理

点击查看代码
#include <iostream>

using std::cin;
using std::cout;
const int N = 5e5 + 10;
struct Node
{
	int l, r;
	int sum;
	int id;
	short tag;
	Node()
	{
		l = r = sum = 0;
		tag = -1;
		id = -1;
	}
} z[N * 80];

bool tag = 0;
int tot;
int mid;
int root[N];

inline void add(const int &rt, const int &l, const int &r, const short &k)
{
	z[rt].sum = (r - l + 1) * k;
	z[rt].tag = k;
}
inline void cov(const int &rt, const int &id)
{
	z[rt].id = id;
}
inline void push_down(const int &rt, const int &l, const int &r)
{
	if (z[rt].id != -1 || z[rt].tag != -1)
	{
		mid = (l + r) >> 1;
		++tot;
		z[tot] = z[z[rt].l];
		if (l == mid && z[tot].id == -1)
			z[tot].id = 0;
		z[rt].l = tot;
		++tot;
		z[tot] = z[z[rt].r];
		if (mid + 1 == r && z[tot].id == -1)
			z[tot].id = 0;
		z[rt].r = tot;
		if (z[rt].tag != -1)
		{
			add(z[rt].l, l, mid, z[rt].tag);
			add(z[rt].r, mid + 1, r, z[rt].tag);
			z[rt].tag = -1;
		}
		if (z[rt].id != -1)
		{
			cov(z[rt].l, z[rt].id);
			cov(z[rt].r, z[rt].id);
			z[rt].id = -1;
		}
		tag = true;
	}
}
inline void push_up(const int &rt)
{
	z[rt].sum = z[z[rt].l].sum + z[z[rt].r].sum;
}
inline int modify(const int &l, const int &r, int rt, const int &nowl, const int &nowr, const int &id, const short &v, bool t)
{
	if (!t)
	{
		++tot;
		z[tot] = z[rt];
		rt = tot;
		if (l == r && z[rt].id == -1)
			z[rt].id = 0;
	}
	if (nowl <= l && r <= nowr)
	{
		add(rt, l, r, v);
		cov(rt, id);
		return rt;
	}
	int mid = (l + r) >> 1;
	tag = 0;
	push_down(rt, l, r);
	bool nw = tag;
	if (nowl <= mid)
		z[rt].l = modify(l, mid, z[rt].l, nowl, nowr, id, v, nw);
	if (nowr > mid)
		z[rt].r = modify(mid + 1, r, z[rt].r, nowl, nowr, id, v, nw);
	push_up(rt);
	return rt;
}
inline int qs(const int &l, const int &r, const int &rt, const int &nowl, const int &nowr)
{
	if (!rt)
		return 0;
	if (z[rt].tag == 0)
		return 0;
	if (nowl <= l && r <= nowr)
		return z[rt].sum;
	int mid = (l + r) >> 1;
	push_down(rt, l, r);
	if (nowl <= mid)
	{
		if (nowr > mid)
			return qs(l, mid, z[rt].l, nowl, nowr) + qs(mid + 1, r, z[rt].r, nowl, nowr);
		else
			return qs(l, mid, z[rt].l, nowl, nowr);
	}
	else
		return qs(mid + 1, r, z[rt].r, nowl, nowr);
}
inline int qid(const int &l, const int &r, const int &rt, const int &p)
{
	if (!rt)
		return 0;
	if (z[rt].id == 0)
		return 0;
	if (l == r)
		return z[rt].id;
	int mid = (l + r) >> 1;
	push_down(rt, l, r);
	if (p <= mid)
		return qid(l, mid, z[rt].l, p);
	else
		return qid(mid + 1, r, z[rt].r, p);
}
inline int pointcov(const int &l, const int &r, int rt, const int &p, const short &k, const int &id)
{
	++tot;
	z[tot] = z[rt];
	rt = tot;
	if (l == r && z[rt].id == -1)
		z[rt].id = 0;
	if (l == r)
	{
		z[rt].id = id;
		z[rt].sum = k;
		return rt;
	}
	int mid = (l + r) >> 1;
	push_down(rt, l, r);
	if (p <= mid)
		z[rt].l = pointcov(l, mid, z[rt].l, p, k, id);
	else
		z[rt].r = pointcov(mid + 1, r, z[rt].r, p, k, id);
	push_up(rt);
	return rt;
}

int main()
{
	int l1, r1, l2, r2, l, r, opt, id;
	short x;
	int n, m, ty;
	cin >> n >> m >> ty;
	int lst = 0;
	int idx = 0;
	for (int i = 1; i <= m; ++i)
	{
		cin >> opt;
		if (opt == 1)
		{
			cin >> l1 >> r1;
			l2 = (1ll * l1 + lst * ty) % n + 1;
			r2 = (1ll * r1 + lst * ty) % n + 1;
			l = std::min(l2, r2);
			r = std::max(l2, r2);
			cout << (lst = qs(1, n, root[idx], l, r)) << '\n';
		}
		else if (opt == 2)
		{
			cin >> l1;
			l = (1ll * l1 + lst * ty) % n + 1;
			id = qid(1, n, root[idx], l);
			if (!id)
				continue;
			++idx;
			root[idx] = pointcov(1, n, root[idx - 1], l, qs(1, n, root[id - 1], l, l), qid(1, n, root[id - 1], l));
		}
		else if (opt == 3)
		{
			cin >> l1 >> r1 >> x;
			l2 = (1ll * l1 + lst * ty) % n + 1;
			r2 = (1ll * r1 + lst * ty) % n + 1;
			l = std::min(l2, r2);
			r = std::max(l2, r2);
			++idx;
			root[idx] = modify(1, n, root[idx - 1], l, r, idx, x, 0);
		}
	}
	return 0;
}

ps:一次区间修改即使加上push_down,访问的总结点数也不超过 \(4\log_2 n\),如果push_down新建了节点,则访问到儿子的时候就不用新建节点了。

7.Souvenirs

点击查看代码
#include <iostream>
#include <algorithm>
#include <vector>
 
using std::cin;
using std::cout;
const int N = 1e5 + 10;
const int oo = 1e9 + 10;
struct Line
{
	int l, r, k;
	int q, id;
};
struct Node1
{
	int mx;
	int l, r;
	Node1()
	{
		mx = 0;
	}
	friend Node1 operator+(const Node1 &a, const Node1 &b)
	{
		Node1 ret;
		ret.mx = std::max(a.mx, b.mx);
		return ret;
	}
} z1[N * 31];
struct Node2
{
	int mn;
	int tag;
	int l, r;
	Node2()
	{
		mn = oo;
		tag = oo;
	}
} z2[N << 1];
 
int tot1, tot2;
int root1, root2;
int a[N];
int ans[(int)2e5 + 10];
int val[N];
std::vector<Line> modi[N];
 
void push_up1(int rt)
{
	z1[rt].mx = std::max(z1[z1[rt].l].mx, z1[z1[rt].r].mx);
}
void push_up2(int rt)
{
	z2[rt].mn = std::min(z2[z2[rt].l].mn, z2[z2[rt].r].mn);
}
void chm2(int rt, int k)
{
	z2[rt].mn = std::min(z2[rt].mn, k);
	z2[rt].tag = std::min(z2[rt].tag, k);
}
void push_down2(int rt)
{
	if (z2[rt].tag != oo)
	{
		if (!z2[rt].l)
			z2[rt].l = ++tot2;
		chm2(z2[rt].l, z2[rt].tag);
		if (!z2[rt].r)
			z2[rt].r = ++tot2;
		chm2(z2[rt].r, z2[rt].tag);
		z2[rt].tag = oo;
	}
}
void modichm1(int l, int r, int &rt, int p, int k)
{
	if (!rt)
		rt = ++tot1;
	if (l == r)
	{
		z1[rt].mx = std::max(z1[rt].mx, k);
		return;
	}
	int mid = (l + r) >> 1;
	if (p <= mid)
		modichm1(l, mid, z1[rt].l, p, k);
	else
		modichm1(mid + 1, r, z1[rt].r, p, k);
	push_up1(rt);
}
void modichm2(int l, int r, int &rt, int nowl, int nowr, int k)
{
	if (!rt)
		rt = ++tot2;
	if (nowl <= l && r <= nowr)
	{
		chm2(rt, k);
		return;
	}
	push_down2(rt);
	int mid = (l + r) >> 1;
	if (nowl <= mid)
		modichm2(l, mid, z2[rt].l, nowl, nowr, k);
	if (nowr > mid)
		modichm2(mid + 1, r, z2[rt].r, nowl, nowr, k);
	push_up2(rt);
}
Node1 query1(int l, int r, int rt, int nowl, int nowr)
{
	if (!rt)
		return Node1();
	if (nowl <= l && r <= nowr)
		return z1[rt];
	int mid = (l + r) >> 1;
	if (nowl <= mid)
	{
		if (nowr > mid)
			return query1(l, mid, z1[rt].l, nowl, nowr) + query1(mid + 1, r, z1[rt].r, nowl, nowr);
		else
			return query1(l, mid, z1[rt].l, nowl, nowr);
	}
	else
		return query1(mid + 1, r, z1[rt].r, nowl, nowr);
}
int query2(int l, int r, int rt, int p)
{
	if (l == r)
		return z2[rt].mn;
	int mid = (l + r) >> 1;
	push_down2(rt);
	if (p <= mid)
		return query2(l, mid, z2[rt].l, p);
	else
		return query2(mid + 1, r, z2[rt].r, p);
}
 
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i)
		cin >> a[i];
	modichm1(0, 1e9, root1, a[1], 1);
	for (int i = 2; i <= n; ++i)
	{
		int now = query1(0, 1e9, root1, a[i], 1e9).mx;
		if (now)
		{
			modi[i].push_back({1, now, a[now] - a[i], 0, 0});
			while (true)
			{
				int now2 = query1(0, 1e9, root1, a[i], (a[now] + a[i]) >> 1).mx;
				if (!now2 || now2 == now)
					break;
				now = now2;
				modi[i].push_back({1, now, a[now] - a[i], 0, 0});
			}
		}
		now = query1(0, 1e9, root1, 0, a[i]).mx;
		if (now)
		{	
			modi[i].push_back({1, now, a[i] - a[now]});
			while (true)
			{
				int now2 = query1(0, 1e9, root1, (a[now] + a[i]) >> 1, a[i]).mx;
				if (!now2 || now2 == now)
					break;
				now = now2;
				modi[i].push_back({1, now, a[i] - a[now], 0, 0});
			}
		}
		modichm1(0, 1e9, root1, a[i], i);
	}
	int m;
	cin >> m;
	for (int i = 1; i <= m; ++i)
	{
		int l, r;
		cin >> l >> r;
		modi[r].push_back({0, 0, l, 1, i});
	}
	for (int i = 1; i <= n; ++i)
	{
		for (Line it : modi[i])
		{
			if (!it.q)
				modichm2(1, n, root2, it.l, it.r, it.k);
			else
				ans[it.id] = query2(1, n, root2, it.k);
		}
	}
	for (int i = 1; i <= m; ++i)
		cout << ans[i] << '\n';
	return 0;
}

ps:ans数组一定要开2e5,不要开成N。

8.Sasha and Array

点击查看代码
#include <iostream>

using std::cin;
using std::cout;
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
struct Mat
{
	int n, m;
	int a[3][3];
	Mat()
	{
		a[1][1] = a[1][2] = a[2][1] = a[2][2] = 0;
	}
	void init(int x)
	{
		*this = Mat();
		n = m = x;
		for (int i = 1; i <= x; ++i)
			a[i][i] = 1;
	}
	friend Mat operator+(const Mat &a, const Mat &b)
	{
		Mat ret;
		ret.n = a.n, ret.m = a.m;
		for (int i = 1; i <= a.n; ++i)
		{
			for (int j = 1; j <= a.m; ++j)
				ret.a[i][j] = (a.a[i][j] + b.a[i][j]) % mod;
		}
		return ret;
	}
	friend Mat operator*(const Mat &a, const Mat &b)
	{
		Mat ret;
		ret.n = a.n, ret.m = b.m;
		for (int i = 1; i <= a.n; ++i)
		{
			for (int j = 1; j <= a.m; ++j)
			{
				for (int k = 1; k <= b.m; ++k)
					ret.a[i][k] = (ret.a[i][k] + 1ll * a.a[i][j] * b.a[j][k] % mod) % mod;
			}
		}
		return ret;
	}
	friend bool operator==(const Mat &a, const Mat &b)
	{
		if (a.n != b.n || a.m != b.m)
			return false;
		for (int i = 1; i <= a.n; ++i)
		{
			for (int j = 1; j <= a.m; ++j)
			{
				if ((a.a[i][j]) != (b.a[i][j]))
					return false;
			}
		}
		return true;
	}
} I, k, c;
struct Node
{
	Mat sum;
	Mat tag;
	Node()
	{
		tag = I;
	}
	friend Node operator+(const Node &l, const Node &r)
	{
		Node ret;
		ret.sum = l.sum + r.sum;
		return ret;
	}
} z[N << 2];

int a[N];

#define root 1, n, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1

void mul(int rt, Mat mul)
{
	z[rt].tag = mul * z[rt].tag;
	z[rt].sum = mul * z[rt].sum;
}
void push_down(int rt)
{
	if (!(z[rt].tag == I))
	{
		mul(rt << 1, z[rt].tag);
		mul(rt << 1 | 1, z[rt].tag);
		z[rt].tag = I;
	}
}
Mat ksm(Mat a, int b)
{
	Mat ret = I;
	for (; b; a = a * a, b >>= 1)
	{
		if (b & 1)
			ret = ret * a;
	}
	return ret;
}
void build(int l, int r, int rt)
{
	if (l == r)
	{
		z[rt].sum = ksm(k, a[l]) * c;
		return;
	}
	int mid = (l + r) >> 1;
	build(lson);
	build(rson);
	z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
void modify(int l, int r, int rt, int nowl, int nowr, Mat f)
{
	if (nowl <= l && r <= nowr)
	{
		z[rt].sum = f * z[rt].sum;
		z[rt].tag = f * z[rt].tag;
		return;
	}
	push_down(rt);
	int mid = (l + r) >> 1;
	if (nowl <= mid)
		modify(lson, nowl, nowr, f);
	if (nowr > mid)
		modify(rson, nowl, nowr, f);
	z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
Node query(int l, int r, int rt, int nowl, int nowr)
{
	if (nowl <= l && r <= nowr)
		return z[rt];
	push_down(rt);
	int mid = (l + r) >> 1;
	if (nowl <= mid)
	{
		if (nowr > mid)
			return query(lson, nowl, nowr) + query(rson, nowl, nowr);
		else
			return query(lson, nowl, nowr);
	}
	else
		return query(rson, nowl, nowr);
}

int main()
{
	I.init(2);
	c.n = 2;
	c.m = 1;
	c.a[1][1] = 1;
	k.n = k.m = 2;
	k.a[1][1] = k.a[1][2] = k.a[2][1] = 1;
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
		cin >> a[i];
	build(root);
	for (int i = 1; i <= m; ++i)
	{
		int opt;
		cin >> opt;
		if (opt == 1)
		{
			int l, r, x;
			cin >> l >> r >> x;
			modify(root, l, r, ksm(k, x));
		}
		else if (opt == 2)
		{
			int l, r;
			cin >> l >> r;
			cout << query(root, l, r).sum.a[2][1] << '\n';
		}
	}
	return 0;
}

ps:modify不要在修改的时候再算ksm,一定要在传参的时候就把ksm出来的矩阵传进去。

9.楼房重建

点击查看代码
#include <iostream>

using std::cin;
using std::cout;
const int N = 1e5 + 10;
struct Node
{
	int cnt;
	int leaf;
	int bian;
	double maxv;
	Node()
	{
		cnt = maxv = 0;
	}
} z[N << 2];

#define root 1, n, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1

int query(int rt, double h)
{
	if (z[rt].leaf)
		return z[rt].maxv > h ? 1 : 0;
	if (z[rt << 1].maxv > h)
	{
		int ret = z[rt].cnt - z[rt << 1].cnt;
		ret += query(rt << 1, h);
		return ret;
	}
	else
		return query(rt << 1 | 1, h);
}
void push_up(int rt)
{
	z[rt].maxv = std::max(z[rt << 1].maxv, z[rt << 1 | 1].maxv);
	z[rt].cnt = z[rt << 1].cnt + query(rt << 1 | 1, z[rt << 1].maxv);
}
void build(int l, int r, int rt)
{
	if (l == r)
	{
		z[rt].leaf = true;
		z[rt].cnt = 1;
		z[rt].bian = rt;
		return;
	}
	int mid = (l + r) >> 1;
	build(lson);
	build(rson);
	push_up(rt);
}
void modify(int l, int r, int rt, int p, double k)
{
	if (l == r)
	{
		z[rt].cnt = 1;
		z[rt].maxv = k;
		return;
	}
	int mid = (l + r) >> 1;
	if (p <= mid)
		modify(lson, p, k);
	else
		modify(rson, p, k);
	push_up(rt);
}

int main()
{
	int n, m;
	cin >> n >> m;
	build(root);
	for (int i = 1; i <= m; ++i)
	{
		int x, y;
		cin >> x >> y;
		modify(root, x, (double)y / x);
		cout << query(1, 0) << '\n';
	}
	return 0;
}

10.Hungry Cow P

点击查看代码
#include <iostream>

using std::cin;
using std::cout;
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
typedef __int128 ll;
struct Node
{
	int sm;
	ll l, r;
	int ls, rs;
	ll alr, rst;
} z[N * 60];

int tot;
int root;
ll inv2;

int query(int rt, ll k, ll l, ll r)
{
	if (!rt)
		return (k <= r - l + 1 ? (l + l + k - 1) % mod * k % mod * inv2 % mod : (l + r) % mod * (r - l + 1) % mod * inv2 % mod);
	if (l == r)
		return l % mod;
	ll mid = (l + r) >> 1;
	if (z[z[rt].ls].alr + k <= mid - l + 1)
		return ((query(z[rt].ls, k, l, mid) + z[rt].sm - z[z[rt].ls].sm) % mod + mod) % mod;
	else
		return ((l + mid) % mod * (mid - l + 1) % mod * inv2 % mod + query(z[rt].rs, k - (mid - l + 1 - z[z[rt].ls].alr) + z[z[rt].ls].rst, mid + 1, r)) % mod;
}
void wrt(ll x)
{
	if (x < 0)
	{
		putchar('-');
		x = -x;
	}
	if (x >= 10)
		wrt(x / 10);
	putchar(x % 10 + '0');
}
void push_up(int rt)
{
	ll l = z[rt].l, r = z[rt].r;
	int ls = z[rt].ls, rs = z[rt].rs;
	ll mid = (l + r) >> 1;
	z[rt].rst = z[rs].rst + (z[ls].rst <= r - mid - z[rs].alr ? 0 : z[ls].rst - (r - mid - z[rs].alr));
	z[rt].alr = z[ls].alr + (z[ls].rst <= r - mid - z[rs].alr ? z[ls].rst + z[rs].alr : r - mid);
	if (z[ls].rst)
		z[rt].sm = (z[ls].sm + query(rs, z[ls].rst, mid + 1, r)) % mod;
	else
		z[rt].sm = (z[ls].sm + z[rs].sm) % mod;
}
void modicov(ll l, ll r, int &rt, ll p, ll k)
{
	if (!rt)
	{
		rt = ++tot;
		z[rt].l = l, z[rt].r = r;
	}
	if (l == r)
	{
		if (k >= 1)
		{
			z[rt].sm = l % mod;
			z[rt].alr = 1;
			z[rt].rst = k - 1;
		}
		else
		{
			z[rt].sm = 0;
			z[rt].alr = 0;
			z[rt].rst = 0;
		}
		return;
	}
	ll mid = (l + r) >> 1;
	if (p <= mid)
		modicov(l, mid, z[rt].ls, p, k);
	else
		modicov(mid + 1, r, z[rt].rs, p, k);
	push_up(rt);
}

int main()
{
	inv2 = 5e8 + 4;
	int u;
	cin >> u;
	while (u--)
	{
		long long d, b;
		cin >> d >> b;
		modicov(1, 1e23, root, d, b);
		cout << z[root].sm << '\n';
	}
	return 0;
}

ps:这道题算的是所有能吃草的天的编号之和,而非天数。

11.Moniphant Sleep

点击查看代码
#include <iostream>
#include <cmath>
#include <set>
#define lowbit(x) x & (-x)

using std::cin;
using std::cout;
const int N = 5e5 + 10;
struct Node
{
	int l, r;
	mutable int v;
	friend bool operator<(const Node &a, const Node &b)
	{
		return (a.l ^ b.l ? a.l < b.l : a.r < b.r);
	}
};

int n, q;
std::set<Node> s;
int sum[N];

inline auto split(int x)
{
	auto it = s.lower_bound({x, 0, 0});
	if (it != s.end() && it->l == x)
		return it;
	it--;
	int l = it->l, r = it->r, v = it->v;
	s.erase(it);
	s.insert({l, x - 1, v});
	return s.insert({x, r, v}).first;
}
inline void cover(int l, int r, int v)
{
	auto it2 = split(r + 1);
	auto it1 = split(l);
	s.erase(it1, it2);
	s.insert({l, r, v});
}
inline void add(int x, int v)
{
	for (; x <= n; x += lowbit(x))
		sum[x] += v;
}
inline int query(int x)
{
	int ret = 0;
	for (; x; x -= lowbit(x))
		ret += sum[x];
	return ret;
}
inline void modiadd(int l, int r)
{
	auto it2 = split(r + 1);
	auto it1 = split(l);
	for (auto i = it1; i != it2; ++i)
	{
		if (i->v != -1)
			i->v++;
	}
}
inline void modimin(int l, int r)
{
	auto it2 = split(r + 1);
	auto it1 = split(l);
	for (auto i = it1; i != it2; ++i)
	{
		if (i->v != -1)
			i->v--;
	}
}
inline void modicov(int l, int r)
{
	auto it2 = split(r + 1);
	auto it1 = split(l);
	for (auto i = it1; i != it2; ++i)
	{
		if (i->v == -1)
			i->v = 0;
	}
}
inline void perform(int l, int r)
{
	auto it2 = split(r + 1);
	auto it1 = split(l);
	for (auto i = it1; i != it2; ++i)
	{
		if (i->v != -1)
		{
			if (i->v)
			{
				add(i->l, -i->v);
				if (i->r < n)
					add(i->r + 1, i->v);
			}
			i->v = -1;
		}
	}
}

int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cin >> n >> q;
	add(1, 5e5);
	s.insert({1, n, -1});
	int B = sqrt(n);
	while (q--)
	{
		int opt, l, r;
		cin >> opt >> l >> r;
		if (opt == 1)
		{
			add(l, 1);
			if (r < n)
				add(r + 1, -1);
			modiadd(l, r);
		}
		else if (opt == 2)
		{
			add(l, -1);
			if (r < n)
				add(r + 1, 1);
			modimin(l, r);
		}
		else if (opt == 3)
			modicov(l, r);
		else if (opt == 4)
			perform(l, r);
		else if (opt == 5)
			cout << query(l) << '\n';
		if (s.size() > B)
		{
			auto it = s.begin();
			while (true)
			{
				auto nxt = std::next(it);
				if (nxt == s.end())
					break;
				if (it->v == nxt->v)
				{
					int l = it->l, r = nxt->r, v = it->v;
					s.erase(it);
					s.erase(nxt);
					it = s.insert({l, r, v}).first;
				}
				else
					it++;
			}
		}
	}
	return 0;
}

ps:ODT要先split(r + 1),再split(l),我这里设了一个阈值,如果块的总个数过多,就扫一遍所有的块,看看相邻的块能不能合并;不过实际上在操作的时候顺带着检查一下这个[l,r]的附近有没有可合并的区间即可,不过懒得写了。

12.栈

点击查看代码
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
const int N = 1e5 + 10;
typedef long long ll;
struct Node
{
	int l, r;
	ll cnt;
	ll rst;
	int val;
	ll sum;
} z[N << 2];
struct Q
{
	int p;
	ll x;
	int y;
	ll q;
};

#define root 1, m, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1

int top = 0;
bool qr[N];
int stk[N << 2];
ll min[N << 2];
ll ans[N];
std::vector<int> id;
std::vector<Q> op[N];

ll query(int rt, ll k, int l, int r)
{
	if (l == r)
		return (k >= z[rt].cnt ? 0 : 1ll * z[rt].val * (z[rt].cnt - k));
	int mid = (l + r) >> 1;
	int ls = rt << 1;
	int rs = rt << 1 | 1; 
	if (z[rs].cnt > k)
		return z[rt].sum - z[rs].sum + query(rs, k, mid + 1, r);
	else
		return query(ls, k - z[rs].cnt + z[rs].rst, l, mid);
}
ll query1(int rt, ll k, int l, int r, ll t)
{
	if (l == r)
		return std::min(t, std::max(0ll, z[rt].cnt - k)) * z[rt].val;
	int mid = (l + r) >> 1;
	int ls = rt << 1;
	int rs = rt << 1 | 1;
	if (z[rs].cnt > k)
	{
		if (t <= (z[rs].rst >= z[ls].cnt ? 0 : z[ls].cnt - z[rs].rst))
			return query1(ls, z[rs].rst, l, mid, t);
		else
			return z[rt].sum - z[rs].sum + query1(rs, k, mid + 1, r, t - (z[rs].rst >= z[ls].cnt ? 0 : z[ls].cnt - z[rs].rst));
	}
	else
		return query1(ls, k - z[rs].cnt + z[rs].rst, l, mid, t);
}
void push_up(int rt, int l, int r)
{
	int ls = rt << 1;
	int rs = rt << 1 | 1;
	int mid = (l + r) >> 1;
	z[rt].cnt = z[rs].cnt + (z[rs].rst >= z[ls].cnt ? 0 : z[ls].cnt - z[rs].rst);
	z[rt].rst = z[ls].rst + (z[rs].rst >= z[ls].cnt ? z[rs].rst - z[ls].cnt : 0);
	z[rt].sum = z[rs].sum + query(ls, z[rs].rst, l, mid);
}
void modify(int l, int r, int rt, int p, ll x, int y)
{
	if (l == r)
	{
		if (x > 0)
		{
			z[rt].cnt = x;
			z[rt].rst = 0;
			z[rt].sum = x * y;
			z[rt].val = y;
		}
		else
		{
			z[rt].cnt = 0;
			z[rt].rst = -x;
			z[rt].sum = 0;
			z[rt].val = 0;
		}
		return;
	}
	int mid = (l + r) >> 1;
	if (p <= mid)
		modify(lson, p, x, y);
	else
		modify(rson, p, x, y);
	push_up(rt, l, r);
}
void qid(int l, int r, int rt, int nowl, int nowr)
{
	if (nowl <= l && r <= nowr)
	{
		z[rt].l = l, z[rt].r = r;
		id.push_back(rt);
		return;
	}
	int mid = (l + r) >> 1;
	if (nowl <= mid)
		qid(lson, nowl, nowr);
	if (nowr > mid)
		qid(rson, nowl, nowr);
}

int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= m; ++i)
	{
		int opt;
		cin >> opt;
		if (opt == 1)
		{
			int l, r, x, y;
			cin >> l >> r >> x >> y;
			op[l].push_back({i, x, y, 0});
			if (r < n)
				op[r + 1].push_back({i, 0, 0, 0});
		}
		else if (opt == 2)
		{
			int l, r;
			ll w;
			cin >> l >> r >> w;
			op[l].push_back({i, -w, 0, 0});
			if (r < n)
				op[r + 1].push_back({i, 0, 0, 0});
		}
		else if (opt == 3)
		{
			int k;
			ll p, q;
			cin >> k >> p >> q;
			op[k].push_back({i, q, 0, 1});
			if (p > 1)
				op[k].push_back({i, p - 1, 0, -1});
			qr[i] = true;
		}
	}
	for (int i = 1; i <= n; ++i)
	{
		for (auto it : op[i])
		{
			if (!it.q)
				modify(root, it.p, it.x, it.y);
			else
			{
				id.clear();
				qid(root, 1, it.p);
				top = 0;
				for (int j = 0; j < (int)id.size(); ++j)
					min[id[j]] = 0;
				for (int j = 0; j < (int)id.size(); ++j)
				{
					ll now = z[id[j]].rst;
					while (top && min[stk[top]] + now >= z[stk[top]].cnt)
						now -= (z[stk[top]].cnt - min[stk[top]]), min[stk[top]] = z[stk[top]].cnt, top--;
					if (top)
						min[stk[top]] += now;
					stk[++top] = id[j];
				}
				ll na = 0;
				ll nowc = 0;
				for (int j = 0; j < (int)id.size(); ++j)
				{
					if (nowc + z[id[j]].cnt - min[id[j]] <= it.x)
					{
						nowc += z[id[j]].cnt - min[id[j]];
						na += query(id[j], min[id[j]], z[id[j]].l, z[id[j]].r);
					}
					else
					{
						na += query1(id[j], min[id[j]], z[id[j]].l, z[id[j]].r, it.x - nowc);
						break;
					}
				}
				ans[it.p] += na * it.q;
			}
		}
	}
	for (int i = 1; i <= m; ++i)
	{
		if (qr[i])
			cout << ans[i] << '\n';
	}
	return 0;
}

ps:在用栈统计每个区间会被pop多少次的时候,我以前是这么写的:

for (int j = 0; j < (int)id.size(); ++j)
{
	ll now = z[id[j]].rst;
	while (top && min[stk[top]] + now >= z[stk[top]].cnt)
		min[stk[top]] = z[stk[top]].cnt, now -= (z[stk[top]].cnt - min[stk[top]]), top--;
	if (top)
		min[stk[top]] += now;
	stk[++top] = id[j];
}

但是显然是错的,因为在now减之前z[stk[top]].cnt已经被赋值成min[stk[top]]了,所以now一直减的都是0。

posted @ 2026-08-13 08:37  SigmaToT  阅读(20)  评论(0)    收藏  举报