专栏文章
题解:P13274 [NOI2025] 三目运算符
P13274题解参与者 3已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @miotktnc
- 此快照首次捕获于
- 2025/12/03 00:56 3 个月前
- 此快照最后确认于
- 2025/12/03 00:56 3 个月前
场外奶龙想了 1h 写了 40min(应该不止),给我糖丸了兄弟。
首先发现 只和 有关,于是考虑 ,发现
110,101 时最后一位会改变。考虑更大的情况,110 的 border 为零看上去似乎互相影响没有那么大,考虑 101 的重复出现,比如 1010101010101,这样第一次就会全部变成 1000000000000,很好处理。考虑
110,这似乎有点难,比如 110 后面跟着很多个 0,那么最后把它变好需要操作 0 的数目次,再比如 11010101,最后操作也是不断把第一个 0 变成 1。通过不断地手玩,打个暴力,我们发现一个惊天大秘密,最后它会变成全部是 1 的状态,而且似乎第一个 0 会每次不断向右移动一个,直到出去。于是我们大胆猜测,长度为 形如 110...... 串的答案其实就是 。这很好证明。考虑归纳法,对于 ,显然操作一次即可,对于 ,我们只考虑 次操作那么就会出现 个
1 最后跟着一个 0。如果 是 1,那么这个 1 会变成一个 0,第 个数会变成 1,最后三个仍然是 110。如果第 是 0 那么最后三个就显然是 110。如果在这个
110 前面增加一段前缀使得它改变了呢?其实不会的,因为开头的 1 变了并不影响这一段第 次操作后会最后出现一个 110,中间的 1 则显然不可能改变。然后你发现这道题找到出现最早的
CPP110 位置和有没有出现过 101 就做完了。线段树即可。#include <bits/stdc++.h>
#define il inline
#define ll long long
using namespace std;
const int N = 4e5, inf = 8e5;
il int ls(int x) {
return 2 * x;
}
il int rs(int x) {
return 2 * x + 1;
}
int p101[N * 4 + 10], p010[N * 4 + 10], p110[N * 4 + 10], p001[N * 4 + 10];//最早出现位置
int pre[N * 4 + 10], suf[N * 4 + 10];//这个节点最开始两个和最后两个(可能只有 1 个要特判)
int tag[N * 4 + 10];
il bool check1(int x, int y, int z) {
return ((x % 2) * 4 + y == z);
}
il bool check2(int x, int y, int z) {
return (x * 2 + y / 2 == z);
}
il void push_up(int now, int s, int t) {
int mid = (s + t) >> 1;
if(t - s + 1 == 2)
pre[now] = suf[now] = pre[ls(now)] * 2 + pre[rs(now)];
else if(t - s + 1 == 3)
pre[now] = pre[ls(now)], suf[now] = (pre[ls(now)] % 2) * 2 + suf[rs(now)];
else pre[now] = pre[ls(now)], suf[now] = suf[rs(now)];
p110[now] = min(p110[ls(now)], p110[rs(now)]);
p101[now] = min(p101[ls(now)], p101[rs(now)]);
p001[now] = min(p001[ls(now)], p001[rs(now)]);
p010[now] = min(p010[ls(now)], p010[rs(now)]);
if(t - s + 1 >= 4) {
if(check1(suf[ls(now)], pre[rs(now)], 6)) p110[now] = min(p110[now], mid);
if(check2(suf[ls(now)], pre[rs(now)], 6)) p110[now] = min(p110[now], mid - 1);
if(check1(suf[ls(now)], pre[rs(now)], 5)) p101[now] = min(p101[now], mid);
if(check2(suf[ls(now)], pre[rs(now)], 5)) p101[now] = min(p101[now], mid - 1);
if(check1(suf[ls(now)], pre[rs(now)], 1)) p001[now] = min(p001[now], mid);
if(check2(suf[ls(now)], pre[rs(now)], 1)) p001[now] = min(p001[now], mid - 1);
if(check1(suf[ls(now)], pre[rs(now)], 2)) p010[now] = min(p010[now], mid);
if(check2(suf[ls(now)], pre[rs(now)], 2)) p010[now] = min(p010[now], mid - 1);
}
else if(t - s + 1 == 3) {
int r = pre[ls(now)] * 2 + suf[rs(now)];
if(r == 6) p110[now] = min(p110[now], mid - 1);
if(r == 5) p101[now] = min(p101[now], mid - 1);
if(r == 1) p001[now] = min(p001[now], mid - 1);
if(r == 2) p010[now] = min(p010[now], mid - 1);
}
}
il void push_tag(int now, int s, int t) {
if(t - s + 1 == 1) pre[now] = 1 - pre[now], suf[now] = 1 - suf[now];
else pre[now] = 3 - pre[now], suf[now] = 3 - suf[now];
tag[now] ^= 1;
swap(p101[now], p010[now]);
swap(p001[now], p110[now]);
}
il void push_down(int now, int s, int t) {
if(tag[now]) {
int mid = (s + t) >> 1;
push_tag(ls(now), s, mid);
push_tag(rs(now), mid + 1, t);
tag[now] = 0;
}
}
int a[N + 10], n, m;
void build(int l, int r, int now) {
tag[now] = 0;
p101[now] = p110[now] = p010[now] = p001[now] = inf;
pre[now] = suf[now] = 0;
if(l == r) {
pre[now] = suf[now] = a[l];
return ;
}
int mid = (l + r) >> 1;
build(l, mid, ls(now));
build(mid + 1, r, rs(now));
push_up(now, l, r);
}
void upd(int ql, int qr, int s, int t, int now) {
if(ql <= s && t <= qr) {
push_tag(now, s, t);
return ;
}
int mid = (s + t) >> 1;
push_down(now, s, t);
if(ql <= mid) upd(ql, qr, s, mid, ls(now));
if(qr > mid) upd(ql, qr, mid + 1, t, rs(now));
push_up(now, s, t);
}
il int qry() {
int ans = 0;
if(p101[1] != inf) ans = 1;
ans = max(ans, n - p110[1] - 1);
return ans;
}
void init() {
cin >> n >> m;
for(int i = 1; i <= n; i++) {
char ch; cin >> ch;
a[i] = ch - '0';
}
build(1, n, 1);
ll ans = 0;
ans ^= qry();
for(int i = 1, l, r; i <= m; i++) {
cin >> l >> r;
upd(l, r, 1, n, 1);
ans ^= (1ll * (i + 1) * 1ll * qry());
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int c, T; cin >> c >> T;
while(T--) init();
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...