HDU 1828 Picture (线段树扫描线求周长并 区间合并)

扫描线求每次的上下已有边长,同时区间合并记录边长的分布情况乘以高度差求出高度的变长


#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 400005

vector<int>v;
int cnt;
struct edge
{
    int l,r;
    int h;
    int tag;
    friend bool operator < (edge a,edge b)
    {
        return a.h<b.h;
    }
} line[maxn];

struct node
{
    int l,r;
    int add;
    int sum;
    int num;
    int lt,rt;
} T[maxn];

void add_edge(int x,int y,int h,int d)
{
    line[cnt].l=x;
    line[cnt].r=y;
    line[cnt].h=h;
    line[cnt++].tag=d;
}

void init(int l,int r,int k)
{
    T[k].l=l;
    T[k].r=r;
    T[k].add=0;
    T[k].sum=0;
    T[k].num=0;
    T[k].lt=T[k].rt=0;
    if(l+1==r) return ;
    int mid=(l+r)>>1;
    init(l,mid,2*k);
    init(mid,r,2*k+1);
}

inline void pushup(int k)
{
    if(T[k].add) T[k].sum=v[T[k].r]-v[T[k].l],T[k].lt=T[k].rt=1;
    else T[k].sum=T[2*k].sum+T[2*k+1].sum,T[k].lt=T[k].rt=0;
    if(T[k].add) T[k].num=1;
    else if(T[k].l+1==T[k].r) T[k].num=0;
    else
    {
        if(T[2*k].rt&&T[2*k+1].lt) T[k].num=T[2*k].num+T[2*k+1].num-1;
        else T[k].num=T[2*k].num+T[2*k+1].num;
        T[k].lt=T[2*k].lt;
        T[k].rt=T[2*k+1].rt;
    }
}

void Insert(int d,int l,int r,int k)
{
    if(T[k].l==l&&T[k].r==r)
    {
        T[k].add+=d;
        pushup(k);
        return ;
    }
    int mid=(T[k].l+T[k].r)>>1;
    if(r<=mid) Insert(d,l,r,2*k);
    else if(l>=mid) Insert(d,l,r,2*k+1);
    else
    {
        Insert(d,l,mid,2*k);
        Insert(d,mid,r,2*k+1);
    }
    pushup(k);
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF&&n)
    {
        v.clear();
        cnt=0;
        for(int i=0; i<n; i++)
        {
            int x1,y1,x2,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            add_edge(x1,x2,y1,-1);
            add_edge(x1,x2,y2,1);
            v.push_back(x1);
            v.push_back(x2);
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        sort(line,line+cnt);
        init(0,v.size()+1,1);
        int ans=0;
        for(int i=0; i<cnt; i++)
        {
            int x=lower_bound(v.begin(),v.end(),line[i].l)-v.begin();
            int y=lower_bound(v.begin(),v.end(),line[i].r)-v.begin();
            int p=T[1].sum;
            if(i) ans+=T[1].num*(line[i].h-line[i-1].h)*2;
            Insert(line[i].tag,x,y,1);
            ans+=abs(T[1].sum-p);
        }
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(HDU 1828 Picture (线段树扫描线求周长并 区间合并))