• 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;
    }
    
  • 相关阅读:
    C基础02天——笔记
    C基础-指针和数组等价转换
    C基础04天—选择排序笔记
    C基础-标准C语言头文件
    C基础-C的关键字
    Ubuntu linux 环境基本使用
    C基础01天——常量变量笔记
    根据评分,用js输出评价星星的样式
    横向滚动条展示 css
    ajax 城市区域选择三级联动
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/14450832.html
Copyright © 2020-2023  润新知