【题目】
BZOJ
简化题意:
数轴上有
n
n
n个炸弹可以表示为
[
a
i
,
b
i
]
[a_i,b_i]
[ai,bi],同时有
m
m
m个建筑(标号
1
∼
m
1\sim m
1∼m)可以表示为
[
l
i
,
r
i
]
[l_i,r_i]
[li,ri],若一个炸弹与一个建筑所表示的线段有交则炸弹可以炸毁这个建筑。支持三种操作:
- 加入一个建筑,按顺序标号
- 查询第 i i i个炸弹能炸毁的标号连续的房子最多多少个
- 查询所有炸弹第二个操作答案的异或和(保证这种操作很少)
n , m ≤ 5 × 1 0 4 n,m\leq 5\times 10^4 n,m≤5×104,操作 1 , 2 ≤ 2 × 1 0 5 1,2\leq 2\times 10^5 1,2≤2×105,操作 3 ≤ 20 3\leq 20 3≤20,坐标范围 ≤ 4 × 1 0 5 \leq 4\times 10^5 ≤4×105
【解题思路】
两个线段
[
l
i
,
r
i
]
,
[
l
j
,
r
j
]
[l_i,r_i],[l_j,r_j]
[li,ri],[lj,rj]相交,当且仅当
l
i
≤
r
j
,
l
j
≤
r
i
l_i\leq r_j,l_j\leq r_i
li≤rj,lj≤ri。
观察到没有增加炸弹的操作,不妨将炸弹表示为二维平面上一个点 ( a i , b i ) (a_i,b_i) (ai,bi),建筑表示为二维平面上一个矩形,横坐标覆盖 [ 1 , r i ] [1,r_i] [1,ri],纵坐标覆盖 [ l i , N ] [l_i,N] [li,N],其中 N N N是一个极大值,这里取 4 × 1 0 5 4\times 10^5 4×105。那么所有能炸毁这个建筑的炸弹均被这个矩形覆盖,不能的不被覆盖。
这样看增加操作,相当于能被矩形覆盖的区域 + 1 +1 +1,不能的置 0 0 0,询问就是单点历史最大值。
写过线段树经典题的我一点也不虚这个标记。
复杂度大概可以用 O ( Q N ) O(Q\sqrt N) O(QN)来表示吧。
标记实现看了别人代码,然后跑不过去。
卡常看了别人代码,然后还是跑不过去。
【参考代码】
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+100,MX=400000,inf=0x3f3f3f3f;
int pcnt,rem;
namespace IO
{
const int LEN=100000;
struct IO
{
char ibuf[LEN],obuf[LEN],*ih,*oh,*lastin,*lastout;
IO(){ih=ibuf+LEN,oh=obuf,lastin=ibuf+LEN,lastout=obuf+LEN-1;}
inline char getchar(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,LEN,stdin),ih==lastin)?EOF:*ih++;}
inline void putchar(char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}
inline int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
inline void reads(char *s)
{
char c=getchar();
while(!isalpha(c)) c=getchar();
while(isalpha(c)) *s++=c,c=getchar();
*s++='\0';
}
inline void write(int x){if(x<0)x=-x,putchar('-');if(x>9)write(x/10);putchar(x%10^48);}
inline void writesp(int x){write(x);putchar(' ');}
inline void writeln(int x){write(x);putchar('\n');}
inline void writes(char *s){while(isalpha(*s))putchar(*s++);}
~IO(){fwrite(obuf,1,oh-obuf,stdout);}
}I;
}
using namespace IO;
namespace Data_Structure
{
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
struct tag
{
int x,y;
inline tag(int _x=0,int _y=-inf):x(_x),y(_y){}
inline friend tag gmax(const tag&a,const tag&b){return tag(Max(a.x,b.x),Max(a.y,b.y));}
inline friend tag merge(const tag&a,const tag&b){return tag(Max(-inf,a.x+b.x),Max(a.y+b.x,b.y));}
inline friend bool equal(const tag&a,const tag&b){return a.x==b.x && a.y==b.y;}
};
struct coor
{
int x,y;
inline coor(int _x=0,int _y=0):x(_x),y(_y){}
inline friend coor gmax(const coor&a,const coor&b){return coor(Max(a.x,b.x),Max(a.y,b.y));}
inline friend coor gmin(const coor&a,const coor&b){return coor(Min(a.x,b.x),Min(a.y,b.y));}
}a[N],b[N];
inline bool cmpx(const coor&a,const coor&b){return a.x<b.x || (a.x==b.x && a.y<b.y);}
inline bool cmpy(const coor&a,const coor&b){return a.y<b.y || (a.y==b.y && a.x<b.x);}
struct node
{
coor mx,mi,p;
tag htag,ntag;
int lc,rc,nmx,hmx;
};
struct KDT
{
#define ls t[x].lc
#define rs t[x].rc
#define sqr(x) ((x)*(x))
int sz;
node t[N];
void build(int &x,int l,int r)
{
x=++sz;int mid=(l+r)>>1;
double avex=0,avey=0,sumx=0,sumy=0;
for(int i=l;i<=r;++i) avex+=b[i].x, avey+=b[i].y;
avex/=(r-l+1); avey/=(r-l+1);
for(int i=l;i<=r;++i) sumx+=sqr(b[i].x-avex), sumy+=sqr(b[i].y-avey);
if(sumx>sumy) nth_element(b+l,b+mid,b+r+1,cmpx);
else nth_element(b+l,b+mid,b+r+1,cmpy);
//nth_element(b+l,b+mid,b+r+1,D?cmpx:cmpy);
t[x].p=t[x].mx=t[x].mi=b[mid];
if(l<mid)
{
build(ls,l,mid-1);
t[x].mx=gmax(t[x].mx,t[ls].mx);t[x].mi=gmin(t[x].mi,t[ls].mi);
}
if(r>mid)
{
build(rs,mid+1,r);
t[x].mx=gmax(t[x].mx,t[rs].mx);t[x].mi=gmin(t[x].mi,t[rs].mi);
}
//printf("%d %d %d %d %d %d %d\n",x,t[x].p.x,t[x].p.y,t[x].mi.x,t[x].mx.x,t[x].mi.y,t[x].mx.y);
}
inline int inmp(const coor&pl,const coor&pr,int l,int r,int L,int R)
{
if(l<=pl.x && pr.x<=r && L<=pl.y && pr.y<=R) return 1;
if(pr.x<l || pl.x>r || pr.y<L || pl.y>R) return -1;
return 0;
}
inline void addval(int x,int va,int vc)
{
t[x].nmx=Max(t[x].nmx+va,vc);t[x].hmx=Max(t[x].nmx,t[x].hmx);
}
inline void addtag(int x,const tag&ht,const tag&nt)
{
t[x].htag=gmax(t[x].htag,merge(t[x].ntag,ht));
t[x].ntag=merge(t[x].ntag,nt);
t[x].hmx=Max(t[x].hmx,Max(t[x].nmx+ht.x,ht.y));
t[x].nmx=Max(t[x].nmx+nt.x,nt.y);
}
inline void pushdown(int x)
{
if(equal(t[x].htag,t[x].ntag) && equal(t[x].htag,tag())) return;
if(ls) addtag(ls,t[x].htag,t[x].ntag);
if(rs) addtag(rs,t[x].htag,t[x].ntag);
t[x].htag=t[x].ntag=tag();
}
void update(int x,int l,int r,int L,int R)
{
//if(pcnt>rem) cerr<<x<<" "<<l<<" "<<r<<" "<<L<<" "<<R<<endl;
if(!x) return;
pushdown(x);int v=inmp(t[x].mi,t[x].mx,l,r,L,R);
//printf("%d %d %d %d %d %d\n",x,v,l,r,L,R);
if(!~v){addtag(x,tag(-inf,0),tag(-inf,0));return;}
if(v){addtag(x,tag(1,0),tag(1,0));return;}
if(inmp(t[x].p,t[x].p,l,r,L,R)==1) addval(x,1,0);
else addval(x,-inf,0);
//if(pcnt>rem) cerr<<x<<" "<<l<<" "<<r<<" "<<L<<" "<<R<<endl;
update(ls,l,r,L,R);update(rs,l,r,L,R);
}
int query(int x,int l,int r)
{
if(!x) return 0;
pushdown(x);int v=inmp(t[x].mi,t[x].mx,l,l,r,r);
if(!~v) return 0;
if(t[x].p.x==l && t[x].p.y==r) return t[x].hmx;
v=0;
if(ls) v+=query(ls,l,r);
if(rs) v+=query(rs,l,r);
return v;
}
int queryall(int x)
{
pushdown(x);int v=t[x].hmx;
if(ls) v^=queryall(ls);
if(rs) v^=queryall(rs);
return v;
}
#undef ls
#undef rs
#undef sqr
}T;
#undef Max
#undef Min
}
using namespace Data_Structure;
namespace DreamLolita
{
int n,m,Q,rt,x,y;
void solution()
{
n=I.read();m=I.read();Q=I.read();
for(int i=1;i<=n;++i) a[i].x=I.read(),a[i].y=I.read(),b[i]=a[i];
T.build(rt,1,n);
for(int i=1;i<=m;++i) x=I.read(),y=I.read(),T.update(rt,1,y,x,MX);
while(Q--)
{
char op=I.getchar(); while(!isalpha(op)) op=I.getchar();
if(op=='A') x=I.read(),y=I.read(),T.update(rt,1,y,x,MX);
else if(op=='C') x=I.read(),I.writeln(T.query(rt,a[x].x,a[x].y));
else I.writeln(T.queryall(rt));
}
//cerr<<clock();
}
}
int main()
{
#ifdef Durant_Lee
freopen("BZOJ5223.in","r",stdin);
freopen("BZOJ5223.out","w",stdout);
#endif
DreamLolita::solution();
return 0;
}