zoukankan      html  css  js  c++  java
  • 【BZOJ2731】三角形覆盖问题

    想象一条平行于(y)轴的扫描线,从低往高扫描。如何确定关键高度才能使每两个关键高度之间分割出的图形易于计算呢?
      
      关键高度有:三角形底边高度、三角形上顶点高度、三角形交点的高度。
      
    ​  如此分割,我们会发现,相邻两条扫描线之间的图形,是一个梯形,那么维护每条扫描线上的有效线段长度即可。
      
      如何维护呢?用一个数组(a_i)表示第(i)格被三角形覆盖了多少次,用一个双向链表记录与每一个与当前扫描线相交的三角形的相交的部分([l,r])
      
      扫描线遇到三角形底端时,将(a)([x,x+d-1])全部加上1,往双向链表中加入([x,x+d-1])
      
      上移扫描线一格的方法是:遍历链表,对于每一个元素([l,r]),将(a_r)减1,将(r)减1,如果(l>r),删除这个元素。什么意思呢?上移一格时,每一个相交的三角形的相交部分([l,r])的最右端会变为不相交,即(a_{r})减1,同时使(r)减1。如此操作,三角形在不相交的时候会被自动删除。
      
      鉴于这道题的神秘数据,直接一格一格向上移动就可以过了...... 如果要优化的话,删除掉那些被其他三角形包含的三角形,就能大幅提升速度。
        
      
      

    Code

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int N=10005,L=2000005;
    int n;
    int s[L],sum;
    ll ans;
    struct Triangle{int x,y,d;}a[N];
    struct Data{int l,r,pre,nex;}b[N];
    int h,cnt;
    void insert(int x,int y){
        b[++cnt]=(Data){x,y,0,0};
        int th=h;
        h=cnt; b[cnt].nex=th; b[th].pre=cnt;
    }
    void delet(int u){
        int pt=b[u].pre,nt=b[u].nex;                                
        if(pt)
            b[pt].nex=nt; 
        else h=nt;
        if(nt)
            b[nt].pre=pt;
    }
    inline bool cmp(const Triangle &u,const Triangle &v){
        if(u.y!=v.y) return u.y<v.y;
        if(u.x!=v.x) return u.x<v.x;
        return u.d<v.d;
    }
    int main(){
        scanf("%d",&n);
        int topy=0;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].d);
            topy=max(topy,a[i].y+a[i].d);
        }
        sort(a+1,a+1+n,cmp);
        ans=0;
        sum=0;
        int last=0,lasty=0;
        for(int y=0,i=1;y<topy;y++){
            for(;a[i].y==y&&i<=n;i++)
                if(a[i].d){
                    for(int k=0;k<a[i].d;k++){
                        if(!s[a[i].x+k]) sum++;
                        s[a[i].x+k]++;
                    }
                    insert(a[i].x,a[i].x+a[i].d-1);
                }
            last=sum;
            for(int k=h,nk;k;k=nk){
                nk=b[k].nex;
                s[b[k].r]--;
                if(!s[b[k].r]) sum--;
                b[k].r--;
                if(b[k].r<b[k].l) delet(k);
            }
            ans+=1LL*(last+sum);
        }
        printf("%.1lf
    ",1.0*ans/2.0);
        return 0;
    }
    
  • 相关阅读:
    015.Delphi插件之QPlugins,FMX插件窗口
    014.Delphi插件之QPlugins,MDI窗口
    013.Delphi插件之QPlugins,模块化代码示例
    012.Delphi插件之QPlugins,多实例内嵌窗口服务
    011.Delphi插件之QPlugins,延时加载服务
    010.Delphi插件之QPlugins,遍历服务接口
    009.Delphi插件之QPlugins,服务的热插拔
    008.Delphi插件之QPlugins,服务的两种调用方法
    007.Delphi插件之QPlugins,插件的卸载和重新加载
    006.Delphi插件之QPlugins,多服务演示
  • 原文地址:https://www.cnblogs.com/RogerDTZ/p/9205046.html
Copyright © 2011-2022 走看看