zoukankan      html  css  js  c++  java
  • [HNOI2012]三角形覆盖问题

    I.[HNOI2012]三角形覆盖问题

    扫描线问题是计算几何里面的一大重点……吗?

    不管怎么说,这道题的确要使用扫描线解决。

    具体来说,因为\(n\)只有\(10000\),考虑使用\(O(n^2)\)的做法并加以剪枝。

    我们首先将所有三角形按照顶点的\(x\)坐标递增顺序。接着,考虑用扫描线维护每一时刻与扫描线相交的所有线段。

    明显我们不能维护每一时刻的状况,不然复杂度吃不消;于是,我们只能维护如下几个时刻的状况:

    1. 当一个三角形被加入的时刻;

    2. 当一个三角形结束的时刻;

    3. 当两条原本相交的线段因为坐标的增加而分离的时刻;

    同时,对于包含关系的线段,我们只保留外面的线段即可。

    在时刻之间的面积,直接采用梯形面积公式即可计算。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int n,m;
    struct LINE{
    	int x,st,ed;
    	LINE(int a=0,int b=0,int c=0){x=a,st=b,ed=c;}
    	friend bool operator <(const LINE &x,const LINE &y){
    		return x.x<y.x;
    	}
    }a[10100];
    struct Line{
    	int st,ed;
    	Line(int a=0,int b=0){st=a,ed=b;}
    	friend bool operator <(const Line &x,const Line &y){
    		return x.st==y.st?x.ed>y.ed:x.st<y.st;
    	}
    }b[10100];
    int Next(){
    	int nex=0x3f3f3f3f;
    	for(int i=1;i<m;i++)if(b[i].ed>b[i+1].st)nex=min(nex,b[i].ed-b[i+1].st);
    	for(int i=1;i<=m;i++)nex=min(nex,b[i].ed-b[i].st);
    	return nex;
    }
    void Decline(int delta){
    	for(int i=1;i<=m;i++)b[i].ed-=delta;
    	int newm=0;
    	for(int i=1;i<=m;i++)if(b[i].ed!=b[i].st)b[++newm]=b[i];
    	m=newm;
    }
    void Reset(){
    	sort(b+1,b+m+1);
    	int newm=1;
    	for(int i=2;i<=m;i++)if(b[i].ed>b[newm].ed)b[++newm]=b[i];
    	m=newm;
    }
    int Calc(){
    	int tot=0;
    	for(int i=1;i<=m;i++)tot+=b[i].ed-max(b[i].st,b[i-1].ed);
    	return tot;
    }
    ll res;
    int main(){
    	scanf("%d",&n);
    	for(int i=1,x,y,z;i<=n;i++)scanf("%d%d%d",&x,&y,&z),a[i]=LINE(x,y,y+z);
    	sort(a+1,a+n+1);
    	a[n+1].x=0x3f3f3f3f;
    	for(int i=1,nexpos=a[1].x,las=0,laspos=-1;i<=n||nexpos<0x3f3f3f3f;){
    		int now=min(nexpos,a[i].x);
    		nexpos=now;
    		int delta=0;
    		if(laspos!=-1)delta=now-laspos;
    		laspos=now;
    		Decline(delta);
    //		printf("PREF:%d\n",now);
    //		for(int i=1;i<=m;i++)printf("[%d,%d]",b[i].st,b[i].ed);puts("");
    		int NOW=Calc();
    		res+=1ll*(NOW+las)*delta;
    		if(nexpos!=a[i].x){las=NOW,nexpos+=Next();continue;}
    		do{b[++m]=Line(a[i].st,a[i].ed),i++;}while(i<=n&&a[i].x==a[i-1].x);
    		Reset();
    //		printf("AFTE:%d\n",now);
    //		for(int i=1;i<=m;i++)printf("[%d,%d]",b[i].st,b[i].ed);puts("");
    		las=Calc();
    		nexpos+=Next();
    	}
    //	printf("%d\n",res);
    	printf("%d.%d\n",res>>1,(res&1)?5:0);
    	return 0;
    }
    

  • 相关阅读:
    关于Kb/s,KB/s的一些知识
    关于停止AsyncTask和Thread的问题
    Android使用layer-list实现三面边框
    MX4连接后adb无法识别解决方法
    浅析LruCache原理
    Android DiskLruCache 硬盘缓存
    NDK、SDK以及JNI的关系
    Android系统提供的开发常用的包名及作用
    MVC学习十三:RouteDebugger插件应用
    MVC学习十二:Ajax.ActionLink用法
  • 原文地址:https://www.cnblogs.com/Troverld/p/14613595.html
Copyright © 2011-2022 走看看