题目
解法
首先题目可以转化成有多个矩形,多个询问,每次询问一个矩形有多少个编号比它大的矩形与其相离。
容斥原理。先延长查询矩形的四条边,发现可以将图划分成九宫格。分别统计在左/右/上/下三格的个数(维护两个条件)。这样显然是会算重的,重复部分就是边角的四个格子(维护三个条件),这个用 (mathtt{cdq}) 分治加树状数组计算即可。
代码
#include <cstdio>
#define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)
template <class T> inline T read(const T sample) {
T x=0; int f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
template <class T> inline void write(const T x) {
if(x<0) return (void) (putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
template <class T> inline T Swap(T &x,T &y) {x^=y^=x^=y;}
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
int n,X[maxn<<1],Y[maxn<<1],lim,tot,c[maxn<<1],cntx,cnty,cnt[maxn],id1[maxn],id2[maxn];
struct Square {int l,r,d,u;} sq[maxn];
struct node {
int x,y,op,ans,id;
bool operator < (const node t) const {
return (x^t.x)?x<t.x:id<t.id;
}
} a[maxn<<1];
int lowbit(int x) {return x&-x;}
void add(int x,int k) {while(x<=lim) c[x]+=k,x+=lowbit(x);}
int ask(int x) {int ret=0; while(x) ret+=c[x],x-=lowbit(x); return ret;}
bool cmpi(node a,node b) {return a.id<b.id;}
void cdq(int l,int r) {
if(l==r) return;
int mid=l+r>>1;
cdq(l,mid),cdq(mid+1,r);
sort(a+l,a+r+1);
rep(i,l,r)
if(a[i].id<=mid) add(a[i].y,a[i].op);
else a[i].ans+=ask(a[i].y);
rep(i,l,r) if(a[i].id<=mid) add(a[i].y,-a[i].op);
}
int main() {
int tot;
n=read(9);
rep(i,1,n)
X[++cntx]=sq[i].l=read(9),Y[++cnty]=sq[i].d=read(9),
X[++cntx]=sq[i].r=read(9)+sq[i].l,Y[++cnty]=sq[i].u=read(9)+sq[i].d;
sort(X+1,X+cntx+1),sort(Y+1,Y+cnty+1);
cntx=unique(X+1,X+cntx+1)-(X+1),cnty=unique(Y+1,Y+cnty+1)-(Y+1);
rep(i,1,n)
sq[i].l=lower_bound(X+1,X+cntx+1,sq[i].l)-(X),
sq[i].r=lower_bound(X+1,X+cntx+1,sq[i].r)-(X),
sq[i].d=lower_bound(Y+1,Y+cnty+1,sq[i].d)-(Y),
sq[i].u=lower_bound(Y+1,Y+cnty+1,sq[i].u)-(Y);
lim=cntx;
fep(i,n,1) cnt[i]+=ask(sq[i].l),add(sq[i].r,1);
memset(c,0,sizeof c);
fep(i,n,1) cnt[i]+=ask(lim-sq[i].r+1),add(lim-sq[i].l+1,1);
memset(c,0,sizeof c);
lim=cnty;
fep(i,n,1) cnt[i]+=ask(sq[i].d),add(sq[i].u,1);
memset(c,0,sizeof c);
fep(i,n,1) cnt[i]+=ask(lim-sq[i].u+1),add(lim-sq[i].d+1,1);
memset(c,0,sizeof c);
tot=0;
fep(i,n,1) {
++tot; a[id1[i]=tot]=(node){sq[i].l,sq[i].d,0,0,tot};
++tot; a[id2[i]=tot]=(node){sq[i].r,sq[i].u,1,0,tot};
}
cdq(1,tot); sort(a+1,a+tot+1,cmpi);
rep(i,1,n) cnt[i]-=a[id1[i]].ans;
tot=0;
fep(i,n,1) {
++tot; a[id1[i]=tot]=(node){sq[i].l,cnty-sq[i].u+1,0,0,tot};
++tot; a[id2[i]=tot]=(node){sq[i].r,cnty-sq[i].d+1,1,0,tot};
}
cdq(1,tot); sort(a+1,a+tot+1,cmpi);
rep(i,1,n) cnt[i]-=a[id1[i]].ans;
tot=0;
fep(i,n,1) {
++tot; a[id1[i]=tot]=(node){cntx-sq[i].r+1,sq[i].d,0,0,tot};
++tot; a[id2[i]=tot]=(node){cntx-sq[i].l+1,sq[i].u,1,0,tot};
}
cdq(1,tot); sort(a+1,a+tot+1,cmpi);
rep(i,1,n) cnt[i]-=a[id1[i]].ans;
tot=0;
fep(i,n,1) {
++tot; a[id1[i]=tot]=(node){cntx-sq[i].r+1,cnty-sq[i].u+1,0,0,tot};
++tot; a[id2[i]=tot]=(node){cntx-sq[i].l+1,cnty-sq[i].d+1,1,0,tot};
}
cdq(1,tot); sort(a+1,a+tot+1,cmpi);
rep(i,1,n) cnt[i]-=a[id1[i]].ans;
rep(i,1,n) puts(cnt[i]>=n-i?"DA":"NE");
return 0;
}