省选专练[HNOI2012]三角形覆盖问题

典型的(对我来说不典型)的多边形的并

通用算法:扫描线+链表

不断往上扫描并且利用一个cover数组暴力改

然后用链表维护添加和删除

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1e6+100;
struct Triangle{
    int x,y,d,l,r;
    friend bool operator <(Triangle A,Triangle B){
        return A.y<B.y;
    }
}T[N];
int n;
int mx=-1;
int pre[N]={};
int nxt[N]={};
void Del(int x){
    pre[nxt[x]]=pre[x];
    nxt[pre[x]]=nxt[x];
}
void Ins(int x,int y){
    pre[nxt[x]]=y;
    nxt[y]=nxt[x];
    pre[y]=x;
    nxt[x]=y;
}
int head,tail,nowh;
int cover[N]={};
bool ins(int x){
    if(!T[x].d)return false;
    for(int i=nxt[head];i!=tail;i=nxt[i]){
        if(T[i].x<=T[x].x&&T[x].x+T[x].d-1<=T[i].x+T[i].d-1-(T[i].d-nowh))return false;	
    }
    Ins(head,x);
    return true;
}
int main(){
//	freopen("2031.in","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&T[i].x,&T[i].y,&T[i].d);
        mx=max(mx,T[i].y+T[i].d);
        T[i].l=T[i].x;
        T[i].r=T[i].x+T[i].d-1;
//		cout<<"here"<<'\n';
    }
    sort(T+1,T+1+n);
//	cout<<"here";
    int ans=0;
    head=0;
    tail=n+1;
    pre[nxt[head]=tail]=head;
//	cout<<"here"<<'\n';
    int last=0;
    int j=1;
//	cout<<"here"<<'\n';
    for(int i=T[1].y;i<=mx;i++){
//		cout<<i<<" "<<'\n';
        int now=last;
        for(int k=nxt[head];k!=tail;k=nxt[k]){
            cover[T[k].r]--;
            if(!cover[T[k].r])now--;
            T[k].r--;
            if(T[k].r<T[k].l)Del(k);
        }
        ans+=now+last;
        while(j<=n&&T[j].y==i){
            if(ins(j)){
                for(int k=T[j].x;k<T[j].x+T[j].d;k++){
                    if(!cover[k])now++;
                    cover[k]++;
                }
            }
            j++;
        }
        last=now;
    }
    printf("%.1lf",ans/2.0);
}

猜你喜欢

转载自blog.csdn.net/fcb_x/article/details/81088769