LOJ

题目

传送门

解法

首先题目可以转化成有多个矩形,多个询问,每次询问一个矩形有多少个编号比它大的矩形与其相离。

容斥原理。先延长查询矩形的四条边,发现可以将图划分成九宫格。分别统计在左/右/上/下三格的个数(维护两个条件)。这样显然是会算重的,重复部分就是边角的四个格子(维护三个条件),这个用 (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;
}
原文地址:https://www.cnblogs.com/AWhiteWall/p/14450832.html