題意:每次插入一條線段或刪除之前一條線段,每次操作線段長度遞增,求插入一段線段時有多少線段被它完全覆蓋。
由於保證線段長度遞增,我們可以用右斷點在合法區間內的減去左端點不在合法區間的,可以用樹狀數組分開維護。
下標需要離散化。
下標可以是負數,這讀入優化坑了我一個小時。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<assert.h>
#include<algorithm>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define erp(i,a,b) for(int i=a;i>=b;--i)
#define clr(x) memset(x,0,sizeof x)
#define LL long long
const int inf = 0x3f3f3f3f;
const int MAXN = 700005;
int N;
void get(int&r)
{
char c, f=0;r=0;
do{ c=getchar();if(c=='-')f=1;} while(c<'0'||c>'9');
do r=r*10+c-'0',c=getchar(); while(c>='0'&&c<='9');
if (f) r=-r;
}
int c1[MAXN*2], c2[MAXN*2];
void add(int *c, int i, int x)
{
for (; i<MAXN*2; i+=i&-i)
c[i] += x;
}
int qsum(int*c, int i)
{
int r = 0;
for (; i>0; i-=i&-i)
r += c[i];
return r;
}
int b[MAXN], to[MAXN];
int d1[MAXN], d2[MAXN];
int dat[MAXN*2], dn;
int idx(int x) { return lower_bound(dat+1,dat+dn+1,x) - dat; }
int main()
{
int cid = 0, len;
while (~scanf("%d", &N))
{
memset(c1, 0, sizeof c1);
memset(c2, 0, sizeof c2);
len = dn = 0;
rep(i, 1, N)
{
get(d1[i]), get(d2[i]);
if (d1[i] == 0)
{
++len;
dat[++dn] = d2[i];
dat[++dn] = d2[i] + len;
}
}
printf("Case #%d:\n", ++cid);
len = 0;
sort(dat+1, dat+dn+1);
dn = unique(dat+1,dat+dn+1)-dat-1;
rep(i, 1, N)
{
if (d1[i] == 0)
{
++len;
to[len] = idx(d2[i] + len);
b[len] = idx(d2[i]);
assert(dat[to[len]] == d2[i]+len);
assert(dat[b[len]] == d2[i]);
printf("%d\n", qsum(c2, to[len]) - qsum(c1, b[len]-1));
add(c1, b[len], 1), add(c2, to[len], 1);
}
else
{
add(c1, b[d2[i]], -1);
add(c2, to[d2[i]], -1);
}
}
}
return 0;
}