P4425 HNOI/AHOI2018 转盘

Day 21。

容易发现最优解里一定存在一种方案,为「一开始停留一段时间,然后一直往下一个取」的形式。通过调整容易证明。

断环成链,直接列出式子:

ans=minni<2nmaxin<jiajj+i

ti=aii(1i2n),然后让 i 平移 n1 位,化简后得:

ans=(n1)+min1in(i+maxij2naj)

相当于对每个 i,求出其后缀最大值 aj。反过来,考虑每个 j,其作为 i 的后缀最大值最小的 i。那么要求的就是 j 前面第一个满足 ai>aji+1,可以单调栈解决。

现在有了修改,直接线段树维护单调栈(楼房重建线段树)即可。

复杂度 O((n+m)log2n)

// Problem: #2495. 「AHOI / HNOI2018」转盘
// Contest: LibreOJ
// URL: https://loj.ac/p/2495
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define mt make_tuple
#define mp make_pair
#define fi first
#define se second

using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
typedef tuple<int, int, int> tu;
bool Med;

const int N = 1e5 + 100;
const int inf = 0x3f3f3f3f;

int n, m, op, a[N << 1];
int mx[N << 3], tr[N << 3];

#define ls x << 1
#define rs x << 1 | 1
#define mid ((l + r) >> 1)

int qry(int l, int r, int c, int x) {
	if (l == r) return mx[x] <= c ? inf : c + l + 1;
	if (mx[rs] < c) return qry(l, mid, c, ls);
	return min(tr[x], qry(mid + 1, r, c, rs));
}

void pup(int l, int r, int x) {
	mx[x] = max(mx[ls], mx[rs]);
	tr[x] = qry(l, mid, mx[rs], ls);
}

void upd(int l, int r, int p, int c, int x) {
	if (l == r) return mx[x] = c, void();
	if (p <= mid) upd(l, mid, p, c, ls);
	else upd(mid + 1, r, p, c, rs);
	pup(l, r, x);
}

void solve() {
	cin >> n >> m >> op;
	for (int i = 1; i <= n; i++) 
		cin >> a[i], a[i + n] = a[i];
	for (int i = 1; i <= (n << 1); i++)
		upd(1, n << 1, i, a[i] - i, 1);
	int lst = 0;
	cout << (lst = min(1 + mx[1], tr[1]) + n - 1) << '\n';
	while (m--) {
		int x, y; cin >> x >> y;
		x ^= op * lst, y ^= op * lst;
		upd(1, n << 1, x, y - x, 1), upd(1, n << 1, x + n, y - n - x, 1);
		cout << (lst = min(1 + mx[1], tr[1]) + n - 1) << '\n';
	}
}

bool Mbe;
int main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cerr << (&Med - &Mbe) / 1048576.0 << " MB\n";
	#ifdef FILE
		freopen("1.in", "r", stdin);
		freopen("1.out", "w", stdout);
	#endif
	int T = 1;
	// cin >> T;
	while (T--) solve();
	cerr << (int)(1e3 * clock() / CLOCKS_PER_SEC) << " ms\n";
	return 0;
}
posted @   Arghariza  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
主题色彩