zoukankan      html  css  js  c++  java
  • 矩形(离散化+树状数组)

    www.cnblogs.com/shaokele/


    1340: 矩形##

      Time Limit: 1 Sec
      Memory Limit: 128 MB

    Description###

      因为对polo忍无可忍, dzf使用圣剑在地上划出了许多纵横交错的沟壑来泄愤。这些沟壑都严格与X轴平行或垂直。
    polo嘲笑了dzf无聊的行为,然后做了一件更加无聊的事。他蹲下来数这些沟壑的条数。数着数着,polo意识到一个问题,那就是因为圣剑的威力太大,划出的沟壑太多,地面就会塌陷。而如果两条水平的沟壑和两条垂直的沟壑相交组成了一个矩形,那么塌陷的危险就会进一步增加。现在polo已经数了n条沟壑,他想知道这些沟壑组成了多少个矩形。
     

    Input###

      第一行一个数n,接下来每行4个数x1,y1,x2,y2,表示沟壑的两个端点(x1,y1),(x2,y2)
     

    Output###

      一个数,组成的矩形个数。
     

    Sample Input###

      4
      0 0 1 0
      0 0 0 1
      1 1 1 -1
      1 1 0 1
      
      
      8
      1 0 4 0
      2 1 2 0
      0 0 0 3
      2 2 2 3
      3 3 3 -1
      0 3 4 3
      4 1 -1 1
      3 2 -1 2
     
    Sample Output
      1
      
      6
      

    题目大意:

      二位直角坐标系中有 n 条水平或竖直的线段
      
      问能组成多少个矩形(相同方向的线段不交)

    题解:

      把所有的 (y) 坐标离散化
      
      把所有的竖线按 (x) 排序
      
      先 (O(n)) 枚举一条竖边,然后枚举与其相交的横边,把它的 (y) 坐标加入树状数组(在树状数组中的位置 (+1) )。预处理完毕
      
      枚举另一条竖边,先判断是否有横边的最右端的 (x) 坐标已经小于当前竖边的 (x) 坐标,找到这条边在树状数组中的位置,删去(在树状数组中的位置 (-1)
      
      然后树状数组做区间查询, (ans) 用数学方法累加
      
      ~~然后 (AC) ~~      妈的调了这么久
      
      (树状数组单点修改,区间查询)
      


    AC代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    using namespace std;
    int n,num,tmp,cnt,cnt1,cnt2,L,R,mid,res,id1,id2;
    ll x1,y1,x2,y2,ans,up,down;
    int c[5005],to[5005];
    ll a[5005];
    struct node1{
    	ll x,l,r;
    }ver[5005];
    struct node2{
    	ll y,l,r;
    }tra[5005];
    bool cmp1(node1 a,node1 b){
    	if(a.x<b.x)return 1;
    	else return 0;
    }
    bool cmp2(node2 a,node2 b){
    	if(a.r<b.r)return 1;
    	else return 0;
    }
    void add(int k,int tot){
    	for(int i=k;i<=tmp;i+=i&(-i))
    		c[i]+=tot;
    }
    int query(int k){
    	int res=0;
    	for(int i=k;i>0;i-=i&(-i))
    		res+=c[i];
    	return res;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
    		if(x1==x2){
    			ver[++cnt1].x=x1;
    			ver[cnt1].l=min(y1,y2);
    			ver[cnt1].r=max(y1,y2);
    			a[++num]=y1;
    			a[++num]=y2;
    		}
    		if(y1==y2){
    			tra[++cnt2].y=y1;
    			tra[cnt2].l=min(x1,x2);
    			tra[cnt2].r=max(x1,x2);
    			a[++num]=y1;
    		}
    	}
    	
    	sort(ver+1,ver+cnt1+1,cmp1);
    	sort(tra+1,tra+cnt2+1,cmp2);
    	sort(a+1,a+num+1);
    	
    	tmp=1;
    	for(int i=2;i<=num;i++)
    		if(a[i]!=a[i-1])
    			a[++tmp]=a[i];
    	
    	
    	for(int i=1;i<=cnt1;i++){
    		memset(c,0,sizeof(c));
    		memset(to,0,sizeof(to));
    		cnt=0;
    		for(int j=1;j<=cnt2;j++)
    			if(tra[j].l<=ver[i].x && ver[i].x<=tra[j].r && ver[i].l<=tra[j].y && tra[j].y<=ver[i].r){
    				res=lower_bound(a+1,a+tmp+1,tra[j].y)-a;
    				to[++cnt]=j;
    				add(res,1);
    			}
    		int p=1;
    		for(int j=i+1;j<=cnt1;j++){
    			while(p<=cnt && ver[j].x>tra[to[p]].r){
    				res=lower_bound(a+1,a+tmp+1,tra[to[p]].y)-a;
    				p++;
    				add(res,-1);
    			}
    			if(p>cnt)break;
    			up=min(ver[i].r,ver[j].r);
    			down=max(ver[i].l,ver[j].l);
    			
    			res=lower_bound(a+1,a+tmp+1,up)-a;
    			id1=res;
    			res=lower_bound(a+1,a+tmp+1,down)-a;
    			id2=res;
    		
    			ll tot=query(id1)-query(id2-1);
    			if(tot>1)ans+=tot*(tot-1)/2;
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    SpringBoot dubbo
    springboot security 安全
    SpringBoot 异步 定时任务 邮件
    elastic search book [ ElasticSearch book es book]
    SpringBoot amqp MQ RabbitMQ
    为Nexus配置阿里云代理仓库【转】
    PLSQL表乱码
    hibernate注解的包
    Spring的refresh()方法相关异常
    spring3.1.1的各个jar作用
  • 原文地址:https://www.cnblogs.com/shaokele/p/9069379.html
Copyright © 2011-2022 走看看