注意到一个很重要的性质:每次添加的线段必定比前面添加的线段长。
所以可以用 左端点>=当前线段左端点的线段数 - 右端点>当前线段右端点的线段数,就是答案。
3 0 0 0 3 0 1 5 0 1 0 0 1 1 0 1 0 0
Case #1: 0 0 0 Case #2: 0 1 0 2HintFor the second case in the sample: At the first add operation,Lillian adds a segment [1,2] on the line. At the second add operation,Lillian adds a segment [0,2] on the line. At the delete operation,Lillian deletes a segment which added at the first add operation. At the third add operation,Lillian adds a segment [1,4] on the line. At the fourth add operation,Lillian adds a segment [0,4] on the line
#include <bits/stdc++.h> using namespace std; #define prt(k) cerr<<#k" = "<<k<<endl typedef long long ll; const ll inf = 0x3f3f3f3f; const int N = 202002 << 1; /****************/ struct Tree { int tree[N]; int low(int x) { return x & -x; } void clear() { memset(tree,0, sizeof tree); } void add(int p, int x) { if (p<=0) return; for (int i=p;i<N;i+=low(i)) tree[i]+=x; } int sum(int p) { int r = 0; for (int i=p;i>0;i-=low(i)) r += tree[i]; return r; } }TL, TR; /****************/ int n; struct data { int op, id; }a[N]; struct P { int l, r; }p[N]; int t[N<<1], tt; int id[N]; int main() { int ca = 1; while (scanf("%d",&n)==1) { int i = 0; for (int i=1;i<=n;i++) scanf("%d%d", &a[i].op, &a[i].id); tt = 0; memset(id, -1, sizeof id); for (int j=1;j<=n;j++) { int op = a[j].op; if (op==0) { ++i; p[i].l = a[j].id; p[i].r = a[j].id + i; id[j] = i; t[tt++] = p[i].l; t[tt++] = p[i].r; } else { ; } } int m = i; sort(t, t+tt); tt = unique(t, t+tt) - t; map<int, int> Lisan; for (int i=0;i<tt;i++) { Lisan[t[i]] = i + 1; } for (int i=1;i<=m;i++) { p[i].l = Lisan[p[i].l]; p[i].r = Lisan[p[i].r]; } TL.clear(); TR.clear(); printf("Case #%d:\n", ca++); for (int i=1;i<=n;i++) { if (a[i].op == 0) { int j = id[i]; int ans = j - 1 - TL.sum(p[j].l - 1); ans -= j - 1 - TR.sum(p[j].r); printf("%d\n", ans); TL.add(p[j].l, 1); TR.add(p[j].r, 1); } if (a[i].op == 1) { int j = a[i].id; TL.add(p[j].l, -1); TR.add(p[j].r, -1); } } } return 0; }