维护一个表,能够插入和删除,并且能够对某一点求前驱和后继。
方法一:线段树 422ms
#include <cstdio>
#include <cstring>
#include <stack>
#include <set>
#include <algorithm>
#define N 50010
using namespace std;
stack<int> st;
int n, m;
int main()
{
char op[3];
int x;
//FILE * fp = fopen("in.txt", "r");
scanf( "%d %d", &n, &m);
set<int> v;
while (m--)
{
scanf( "%s", op);
if (op[0] == 'D')
{
scanf( "%d", &x);
st.push(x);
v.insert(x);
}
else if (op[0] == 'R')
{
int cc = st.top();
st.pop();
v.erase(cc);
}
else {
scanf( "%d", &x);
int ans;
if (v.count(x) == 1)ans = 0;
else if (v.size() == 0) ans = n;
else
{
int l, r;
set<int>::iterator it = v.upper_bound(x);
if (it == v.end())r = n + 1, l = (*(--it)), ans = (r - l - 1);
else if (it == v.begin())r = (*it), l = 0, ans = (r - l - 1);
else {
set<int>::iterator itt = (--it);
it++;
ans = (*it - *itt - 1);
}
}
printf("%d", ans);
if (m)puts("");
}
}
// getchar();
return 0;
}
#include <cstdio>
#include <cstring>
#include <stack>
#include <set>
#include <algorithm>
#define N 50010
using namespace std;
stack<int> st;
int n, m;
int main()
{
char op[3];
int x;
//FILE * fp = fopen("in.txt", "r");
scanf( "%d %d", &n, &m);
set<int> v;
while (m--)
{
scanf( "%s", op);
if (op[0] == 'D')
{
scanf( "%d", &x);
st.push(x);
v.insert(x);
}
else if (op[0] == 'R')
{
int cc = st.top();
st.pop();
v.erase(cc);
}
else {
scanf( "%d", &x);
int ans;
if (v.count(x) == 1)ans = 0;
else if (v.size() == 0) ans = n;
else
{
int l, r;
set<int>::iterator it = v.upper_bound(x);
if (it == v.end())r = n + 1, l = (*(--it)), ans = (r - l - 1);
else if (it == v.begin())r = (*it), l = 0, ans = (r - l - 1);
else {
set<int>::iterator itt = (--it);
it++;
ans = (*it - *itt - 1);
}
}
printf("%d", ans);
if (m)puts("");
}
}
// getchar();
return 0;
}
法三:树状数组+二分查找 这个懒得写了