P1503 鬼子进村
链接
https://www.luogu.com.cn/problem/P1503
思路
树状数组。本来的想法是由于删掉了某个村庄,那么可以统一修改左边村庄的右边界为x-1;右边村庄的左边界为x+1;但是要用到两棵可持久化线段树。
所以想到:直接对某个节点设0/1状态。被毁了就设置成0,然后两次二分统计区间和满足条件的最大长度即可。
代码
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long long
const int N = 5e4 + 10;
int lowbit(int x) { return x & (-x); }
int tree[N];
void add(int x, int t)
{
while (x < N)
{
tree[x] += t;
x += lowbit(x);
}
return;
}
int sum(int x)
{
int a = 0;
while (x > 0)
{
a += tree[x];
x -= lowbit(x);
}
return a;
}
void solve()
{
stack<int>st;
int n, m; cin >> n >> m;
for (int i = 1; i <= n; i++)add(i, 1);
for (int i = 0; i < m; i++)
{
char d; int x;
cin >> d;
if (d == 'D')
{
cin >> x;
st.push(x);
add(x, -1);
}
else if (d == 'Q')
{
cin >> x;
if (sum(x)-sum(x-1) == 0)cout << 0 << '\n';
else
{
int L, R;
int l = 1; int r = x - 1;
while (l <= r)
{
int m = (l + r) >> 1;
if (sum(r) - sum(m - 1) == r - m + 1)
{
r = m - 1;
}
else l = m + 1;
}
L = l;
l = x , r = n;
while (l < r)
{
int m = (l + r + 1) >> 1;
if (sum(m) - sum(l - 1) == m - l + 1)l = m;
else r = m - 1;
}
R = l;
cout << R - L + 1 << '\n';
}
}
else {
int now = st.top();
st.pop();
add(now, 1);
}
}
}
signed main()
{
IOS;
solve();
return 0;
}

浙公网安备 33010602011771号