zoukankan      html  css  js  c++  java
  • [COCI2018-2019#2] Sunčanje

    前言

    好久没写得这么爽了~

    题目

    洛谷

    LOJ

    讲解

    在我看来,这是一道码农题。

    对于每个矩形,我们考虑计算出顺序在它之后(即可能将其覆盖)没有与它相交的矩形个数,我们将其取名为合法矩形,然后与顺序在它之后的矩形个数比较即可得出答案。

    考虑容斥。

    对于每个矩形,我们可以将其四条边无限延长,然后整个平面就被分为了 (9) 个格子。对于上下左右四个方向各三个格子统计出有多少个合法矩形,记录下来。

    显然四个角的合法矩形被计算了两次,减掉即可。这就是个简单的偏序问题了,使用 ( t cdq) 即可求解。

    小优化:在 ( t cdq) 过程中,显然可以使用归并排序优化时间,当然不优化也行,这道题时限很宽。

    注意 ( t cdq) 排序时的顺序,求解时的边界问题以及树状数组的清空(因为我都挂过qwq)。

    ( t cdq) 套树状数组,时间复杂度是 (O(nlog^2n))

    代码

    我的代码实现过于冗长,主要是因为四个角打了四个 ( t cdq)。 /jk

    而且我为了方便,将整个数组翻转了,看代码时不要误解了。

    //12252024832524
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define TT template<typename T>
    using namespace std; 
    
    typedef long long LL;
    const int MAXN = 200005;
    int n,lenx,leny;
    int lshx[MAXN],lshy[MAXN];
    
    LL Read()
    {
    	LL x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
    
    int b[MAXN];
    int lowbit(int x){return (x & -x);}
    void Add(int x,int M,int val){for(int i = x;i <= M;i += lowbit(i)) b[i] += val;}
    int Sum(int x){int ret = 0;for(int i = x;i >= 1;i -= lowbit(i)) ret += b[i]; return ret;}
    void clr(int x){for(int i = 1;i <= x;++ i) b[i] = 0;}
    int cnt[MAXN];
    struct Rectangle 
    {
    	int x,y,x2,y2;//lower left,upper right,ID
    }c[MAXN];
    struct node
    {
    	int x,y,f,ID,ori;//f=1:calculate,f=0:update
    	node(){}
    	node(int x1,int y1,int f1,int ID1,int ori1){
    		x = x1;
    		y = y1;
    		f = f1;
    		ID = ID1;
    		ori = ori1;
    	}
    }p[MAXN],q[MAXN];
    
    void cdq1(int l,int r)//upper left
    {
    	if(l == r) return;
    	int mid = (l+r) >> 1;
    	cdq1(l,mid); cdq1(mid+1,r);
    	int I = l,J = mid+1,K = l;
    	while(I <= mid && J <= r)
    		if(p[I].x < p[J].x || (p[I].x == p[J].x && p[I].ori < p[J].ori)) q[K++] = p[I++];//Pay attention to the order when x is equal to another. 
    		else q[K++] = p[J++];
    	while(I <= mid) q[K++] = p[I++];
    	while(J <= r) q[K++] = p[J++];
    	for(int i = l;i <= r;++ i) 
    	{
    		p[i] = q[i];
    		if(!p[i].f && p[i].ori <= mid)
    			Add(leny-p[i].y+1,leny,1);
    		else if(p[i].f && p[i].ori > mid)
    			cnt[p[i].ID] -= Sum(leny-p[i].y+1);
    	}
    	for(int i = l;i <= r;++ i) 
    		if(!p[i].f && p[i].ori <= mid)
    			Add(leny-p[i].y+1,leny,-1);
    }
    void cdq2(int l,int r)//lower left
    {
    	if(l == r) return;
    	int mid = (l+r) >> 1;
    	cdq2(l,mid); cdq2(mid+1,r);
    	int I = l,J = mid+1,K = l;
    	while(I <= mid && J <= r)
    		if(p[I].x < p[J].x || (p[I].x == p[J].x && p[I].ori < p[J].ori)) q[K++] = p[I++];
    		else q[K++] = p[J++];
    	while(I <= mid) q[K++] = p[I++];
    	while(J <= r) q[K++] = p[J++];
    	for(int i = l;i <= r;++ i) 
    	{
    		p[i] = q[i];
    		if(!p[i].f && p[i].ori <= mid)
    			Add(p[i].y,leny,1);
    		else if(p[i].f && p[i].ori > mid)
    			cnt[p[i].ID] -= Sum(p[i].y);
    	}
    	for(int i = l;i <= r;++ i) 
    		if(!p[i].f && p[i].ori <= mid)
    			Add(p[i].y,leny,-1);
    }
    void cdq3(int l,int r)//upper right
    {
    	if(l == r) return;
    	int mid = (l+r) >> 1;
    	cdq3(l,mid); cdq3(mid+1,r);
    	int I = l,J = mid+1,K = l;
    	while(I <= mid && J <= r)
    		if(p[I].x < p[J].x || (p[I].x == p[J].x && p[I].ori > p[J].ori)) q[K++] = p[I++];
    		else q[K++] = p[J++];
    	while(I <= mid) q[K++] = p[I++];
    	while(J <= r) q[K++] = p[J++];
    	for(int i = r;i >= l;-- i) 
    	{
    		p[i] = q[i];
    		if(!p[i].f && p[i].ori <= mid)
    			Add(leny-p[i].y+1,leny,1);
    		else if(p[i].f && p[i].ori > mid)
    			cnt[p[i].ID] -= Sum(leny-p[i].y+1);
    	}
    	for(int i = r;i >= l;-- i) 
    		if(!p[i].f && p[i].ori <= mid)
    			Add(leny-p[i].y+1,leny,-1);
    }
    void cdq4(int l,int r)//lower right
    {
    	if(l == r) return;
    	int mid = (l+r) >> 1;
    	cdq4(l,mid); cdq4(mid+1,r);
    	int I = l,J = mid+1,K = l;
    	while(I <= mid && J <= r)
    		if(p[I].x < p[J].x || (p[I].x == p[J].x && p[I].ori > p[J].ori)) q[K++] = p[I++];
    		else q[K++] = p[J++];
    	while(I <= mid) q[K++] = p[I++];
    	while(J <= r) q[K++] = p[J++];
    	for(int i = r;i >= l;-- i) 
    	{
    		p[i] = q[i];
    		if(!p[i].f && p[i].ori <= mid)
    			Add(p[i].y,leny,1);
    		else if(p[i].f && p[i].ori > mid)
    			cnt[p[i].ID] -= Sum(p[i].y);
    	}
    	for(int i = r;i >= l;-- i) 
    		if(!p[i].f && p[i].ori <= mid)
    			Add(p[i].y,leny,-1);
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read();
    	for(int i = n;i >= 1;-- i) 
    	{
    		c[i].x = Read(),c[i].y = Read(),c[i].x2 = Read(),c[i].y2 = Read();//reverse order
    		c[i].x2 += c[i].x-1;
    		c[i].y2 += c[i].y-1;
    		lshx[i<<1] = c[i].x; lshx[(i<<1)-1] = c[i].x2;
    		lshy[i<<1] = c[i].y; lshy[(i<<1)-1] = c[i].y2;
    	}
    	//Discretization 
    	sort(lshx+1,lshx+(n<<1)+1); sort(lshy+1,lshy+(n<<1)+1);
    	lenx = unique(lshx+1,lshx+(n<<1)+1) - lshx - 1; leny = unique(lshy+1,lshy+(n<<1)+1) - lshy - 1;
    	for(int i = 1;i <= n;++ i) c[i].x = lower_bound(lshx+1,lshx+lenx+1,c[i].x) - lshx,c[i].x2 = lower_bound(lshx+1,lshx+lenx+1,c[i].x2) - lshx;
    	for(int i = 1;i <= n;++ i) c[i].y = lower_bound(lshy+1,lshy+leny+1,c[i].y) - lshy,c[i].y2 = lower_bound(lshy+1,lshy+leny+1,c[i].y2) - lshy;
    	//4 directions
    	for(int i = 1;i <= n;++ i) cnt[i] += Sum(c[i].x-1),Add(c[i].x2,lenx,1); clr(lenx); //left
    	for(int i = 1;i <= n;++ i) cnt[i] += Sum(lenx-c[i].x2),Add(lenx-c[i].x+1,lenx,1); clr(leny); //right
    	for(int i = 1;i <= n;++ i) cnt[i] += Sum(c[i].y-1),Add(c[i].y2,leny,1); clr(leny); //down
    	for(int i = 1;i <= n;++ i) cnt[i] += Sum(leny-c[i].y2),Add(leny-c[i].y+1,leny,1); clr(leny); //up
    	//4 corners 
    	for(int i = 1;i <= n;++ i) p[i<<1] = node(c[i].x-1,c[i].y2+1,1,i,i<<1),p[(i<<1)-1] = node(c[i].x2,c[i].y,0,i,(i<<1)-1); cdq1(1,n<<1);
    	for(int i = 1;i <= n;++ i) p[i<<1] = node(c[i].x-1,c[i].y-1,1,i,i<<1),p[(i<<1)-1] = node(c[i].x2,c[i].y2,0,i,(i<<1)-1); cdq2(1,n<<1);
    	for(int i = 1;i <= n;++ i) p[i<<1] = node(c[i].x2+1,c[i].y2+1,1,i,i<<1),p[(i<<1)-1] = node(c[i].x,c[i].y,0,i,(i<<1)-1); cdq3(1,n<<1);
    	for(int i = 1;i <= n;++ i) p[i<<1] = node(c[i].x2+1,c[i].y-1,1,i,i<<1),p[(i<<1)-1] = node(c[i].x,c[i].y2,0,i,(i<<1)-1); cdq4(1,n<<1);
    	//There are so many "+1" and "-1". Pay attention to the boundary.
    	//print
    	for(int i = n;i >= 1;-- i)
    	{
    		if(cnt[i] != i-1) printf("NE
    ");
    		else printf("DA
    ");
    	}
    	return 0;
    }
    //sorry for my poor English
    //sorry for my poor English
    
  • 相关阅读:
    Centos7部署jenkins
    查看杀死django进程
    【填坑】python3 manage.py migrate:?: (mysql.W002) MySQL Strict Mode is not set for database connection 'default'
    Amazon S3 加密
    向 Elastic Beanstalk 环境中添加数据库
    Amazon RDS 监控概览
    AWS Lambda 环境变量
    使用 DynamoDB Auto Scaling 自动管理吞吐容量
    使用 Amazon Aurora Auto Scaling 扩展 Aurora 副本
    ECS 服务 Auto Scaling 和 Application Auto Scaling
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/14464866.html
Copyright © 2011-2022 走看看