题解:
对于新插入的线段,查询有多少个线段左端点大于等于该线段的左端点。 再查询有多少个线段的右端点大于该线段右端点, 两者之差就是答案。
这里注意两个问题,一个是离散化,第二个这道题时间卡的可能比较严,线段树貌似会超时~
好久没写离散化了。。。生疏了
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1000005;
int n;
//----------------------------------------------------------
int Hash[maxn * 2];
int Hash_num;
int HASH(int u){
return lower_bound(Hash + 1,Hash + Hash_num,u) - Hash;
}
void Hash_debug(){
for(int i = 1; i < Hash_num; i++)
printf("%d ",Hash[i]);
puts("");
}
//-----------------------------------------------------------
int C[2][maxn];
int lowbit(int x){
return x & (-x);
}
int sum(int op,int x){
int ret = 0;
while(x > 0){
ret += C[op][x];
x -= lowbit(x);
}
return ret;
}
void add(int op,int x,int value){
while(x <= Hash_num){
C[op][x] += value;
x += lowbit(x);
}
}
//-----------------------------------------------------------
struct Input{
int op,id,lv;
}input[maxn];
int pid[maxn];
//------------------------------------------------------------
int main(){
int Case = 1;
while(scanf("%d",&n) != EOF){
int cnt = 1;
Hash_num = 1;
Hash[Hash_num++] = 0;
memset(C,0,sizeof(C));
for(int i = 0; i < n; i++){
scanf("%d%d",&input[i].op,&input[i].lv);
if(input[i].op == 0){
input[i].lv ++;
Hash[Hash_num++] = input[i].lv;
Hash[Hash_num++] = input[i].lv + cnt;
pid[cnt] = i;
input[i].id = cnt ++;
}
}
sort(Hash + 1,Hash + Hash_num);
Hash_num = unique(Hash + 1,Hash + Hash_num) - Hash;
//Hash_debug();
printf("Case #%d:\n",Case++);
for(int i = 0; i < n; i++){
if(input[i].op == 0){
int sum1 = sum(0,Hash_num);
int sum2 = sum(1,Hash_num);
int lv = HASH(input[i].lv);
int rv = HASH(input[i].lv + input[i].id);
int sum11 = sum1 - sum(0,lv - 1);
int sum22 = sum2 - sum(1,rv);
printf("%d\n",abs(sum11 - sum22));
add(0,lv,1);
add(1,rv,1);
}
else{
int id = pid[input[i].lv];
int lv = HASH(input[id].lv);
int rv = HASH(input[id].lv + input[id].id);
add(0,lv,-1);
add(1,rv,-1);
}
}
}
return 0;
}