题意:
一段连续的区间,两个操作:
D x: 破坏点x。
Q x:查询与x直接和间接相连的最长区间。
R x:恢复上一个被破坏的点。
#include<bits/stdc++.h>
using namespace std;
// clock_t start, end;
// start = clock();
// end = clock();
// cout << (double) (end - start) / CLOCKS_PER_SEC << endl;
//#define int long long
#define rep(i, x, y) for(auto i=(x);i<=(y);++i)
#define dep(i, x, y) for(auto i=(x);i>=(y);--i)
#define gcd(a, b) __gcd(a,b)
const long long mod = 1e9 + 7;
const int maxn = 4e6 + 100;
int lowbit(int x) { return x & -x; }
bool ispow(int n) { return (n & (n - 1)) == 0; }//O(1) 判断是否是 2^k(2的k次方)
int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
struct node {
int l, r;
int ll, rr, len;
} tree[4 * 50050];
void build(int i, int l, int r) {
tree[i].l = l;
tree[i].r = r;
tree[i].ll = tree[i].rr = r - l + 1;
tree[i].len = r - l + 1;
if (l == r) {
return;
}
build(i << 1, l, (int) floor((r + l) / 2.0));
build((i << 1) + 1, (int) floor((r + l) / 2.0) + 1, r);
}
void update(int i, int x, int cnt) {
if (tree[i].l == tree[i].r) {
tree[i].ll = tree[i].rr = cnt;
return;
}
int mid = (tree[i].l + tree[i].r) >> 1;
if (mid >= x) {
update(i << 1, x, cnt);
} else {
update((i << 1) + 1, x, cnt);
}
if (tree[(i << 1)].ll + tree[(i << 1) + 1].rr == tree[i].len)
tree[i].ll = tree[i].rr = tree[i].len;
else {
if (tree[i << 1].ll == tree[i << 1].len)
tree[i].ll = tree[i << 1].len + tree[(i << 1) + 1].ll;
else
tree[i].ll = tree[i << 1].ll;
if (tree[(i << 1) + 1].rr == tree[(i << 1) + 1].len)
tree[i].rr = tree[(i << 1) + 1].len + tree[i << 1].rr;
else
tree[i].rr = tree[(i << 1) + 1].rr;
}
}
int que(int i, int x) {
if (i == 1) {
if (tree[i].ll) {
if ((tree[i].l + tree[i].ll - 1) >= x)
return tree[i].ll;
}
if (tree[i].rr) {
if ((tree[i].r - tree[i].rr + 1) <= x)
return tree[i].rr;
}
}
if (tree[i].ll) {
if ((tree[i].l + tree[i].ll - 1) >= x)
return tree[i].ll + tree[i - 1].rr;
}
if (tree[i].rr) {
if ((tree[i].r - tree[i].rr + 1) <= x)
return tree[i].rr + tree[i + 1].ll;
}
if (tree[i].l == tree[i].r)
return 0;
int mid = (tree[i].l + tree[i].r) >> 1;
if (mid >= x)
return que(i << 1, x);
else
return que((i << 1) + 1, x);
}
int main() {
int n, m;
int q[50005];
while (cin >> n >> m) {
build(1, 1, n);
int flag = 0;
for (int i = 1; i <= m; i++) {
char c[5];
cin >> c;
if (c[0] == 'D') {
int k;
cin >> k;
q[++flag] = k;
update(1, k, 0);
} else if (c[0] == 'Q') {
int k;
cin >> k;
cout << que(1, k) << endl;
} else {
if (flag == 0)continue;
int k = q[flag--];
update(1, k, 1);
}
}
}
return 0;
}
本文介绍了一种基于线段树的数据结构实现,用于处理区间上的破坏、恢复及查询最长连续区间的问题。通过更新线段树节点的状态来维护区间信息,并支持高效查询与更新操作。
572

被折叠的 条评论
为什么被折叠?



