题意:
给 n 个 A类区间和 m 个 B 类区间,区间的左右端点为 l , r. 给出 q 次修改,每次询问加入一个 A 类区间或者 B 类区间,求每次修改后有交集的A 类与B类区间的对数。
思路:
- 求与 【l , r】区间相交的区间个数,可以先求出与它不相交的区间个数,也就是右端点比 l 小 ,或者左端点比 r 大的区间的个数(这个经常用),然后就可以用线段树维护,把区间的几个端点用4个线段树维护,就可以很快求出区间个数。
- 所以初始答案,我们只需要遍历 n 个 A 类区间,求出 B 中与它相交的个数。修改的时候只要相应的用线段树查询一下就好了。注意要离散化。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<cstring>
#include<bitset>
#include<stack>
using namespace std;
typedef long long ll;
const int maxn=4e6+7;
const int rr = 233;
const int mod = 1e9 + 7;
int T;
int sum[6][maxn];
int n,m,q;
int l1[maxn],l2[maxn],r1[maxn],r2[maxn],val[maxn],k;
struct node{
int id,l,r;
}num[maxn];
void pushdown(int rt){
for(int i = 1; i <= 4; i ++){
sum[i][rt] = (sum[i][rt << 1] + sum[i][rt << 1 | 1]);
}
return ;
}
void update(int id,int pos,int l,int r,int rt){
if(l == r){
sum[id][rt] ++;
return ;
}
int mid = (l + r) / 2;
if(pos <= mid) update(id,pos,l,mid,rt << 1);
if(pos > mid) update(id,pos,mid + 1 ,r ,rt << 1|1);
pushdown(rt);
}
int query(int id,int L,int R,int l,int r,int rt){
int s = 0;
if(L <= l && R >= r){
return sum[id][rt];
}
int mid = (l + r) / 2;
if(L <= mid) s += query(id,L,R,l,mid,rt << 1);
if(R > mid) s += query(id,L,R,mid + 1,r,rt << 1 | 1);
return s;
}
int main (){
scanf("%d",&T);
int TT = T;
int tot = 1;
while(T--){
scanf("%d",&n);
k = 0;
for(int i = 1; i <= n ; i++){
scanf("%d%d",&l1[i],&r1[i]);
val[k++] = l1[i];
val[k++] = r1[i];
}
scanf("%d",&m);
for(int i = 1; i <= m ; i++){
scanf("%d%d",&l2[i],&r2[i]);
val[k++] = l2[i];
val[k++] = r2[i];
}
scanf("%d",&q);
for(int i = 1; i <= q; i ++){
scanf("%d%d%d",&num[i].id,&num[i].l,&num[i].r);
val[k++] = num[i].l;
val[k++] = num[i].r;
}
sort(val ,val + k);
k = unique(val,val + k) - val;
memset(sum,0,sizeof(sum));
for(int i = 1; i <= n; i ++){
l1[i] = lower_bound(val,val + k,l1[i]) - val + 1;
r1[i] = lower_bound(val,val + k,r1[i]) - val + 1;;
update(1,l1[i],1,k,1);
update(2,r1[i],1,k,1);
}
for(int i = 1; i <= m; i ++){
l2[i] = lower_bound(val,val + k,l2[i]) - val + 1;
r2[i] = lower_bound(val,val + k,r2[i]) - val + 1;
update(3,l2[i],1,k,1);
update(4,r2[i],1,k,1);
}
ll ans = 0;
for(int i = 1; i <= n; i ++){
ans += m;
if(l1[i] != 1) ans -= query(4,1,l1[i] - 1,1,k,1);
if(r1[i] != k) ans -= query(3,r1[i] + 1,k,1,k,1);
}
printf ("Case %d: %lld\n",tot++,ans);
for(int i = 1; i <= q; i ++){
int l = lower_bound(val,val + k,num[i].l) - val + 1;
int r = lower_bound(val,val + k,num[i].r) - val + 1;
if(num[i].id == 1){
ans += m;
if(l != 1) ans -= query(4,1,l - 1,1,k,1);
if(r != k) ans -= query(3,r + 1,k,1,k,1);
update(1,l,1,k,1);
update(2,r,1,k,1);
n++;
}
if(num[i].id == 2){
ans += n;
if(l != 1) ans -= query(2,1,l - 1,1,k,1);
if(r != k) ans -= query(1,r + 1,k,1,k,1);
update(3,l,1,k,1);
update(4,r,1,k,1);
m++;
}
printf ("%lld\n",ans);
}
}
return 0;
}