洛谷 P1856 [USACO5.5]矩形周长Picture

来源:互联网 发布:head first java 编辑:程序博客网 时间:2024/06/13 09:32

题目背景
墙上贴着许多形状相同的海报、照片。它们的边都是水平和垂直的。每个矩形图片可能部分或全部的覆盖了其他图片。所有矩形合并后的边长称为周长。
题目描述
编写一个程序计算周长。
这里写图片描述
如图1所示7个矩形。
这里写图片描述
如图2所示,所有矩形的边界。所有矩形顶点的坐标都是整数。
输入输出格式
输入格式:
输入文件的第一行是一个整数N(0<=N<5000),表示有多少个矩形。接下来N行给出了每一个矩形左下角坐标和右上角坐标(所有坐标的数值范围都在-10000到10000之间)。
输出格式:
输出文件只有一个正整数,表示所有矩形的周长。
输入输出样例
输入样例#1:
7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16
输出样例#1:
228

分析:
1.每个矩形由两条横向边和两条纵向边组成。
2.对于横向边,按纵坐标排序。设当前讨论的边为 A [s , t]
如果A是某个矩形的靠下的边,在树中查询[s,t]区间中被覆盖的长度为x,那么加上这条边后将增加(t-s-x);
如果A是某个矩形的靠上的边,先删除它的对应边,再在树中查询[s,t]区间中被覆盖的长度为x,那么加上这条边后将增加(t-s-x);
3、对于纵向边,按横坐标排序,讨论方法与横向边相同。
注意建树方式是以单位线段为叶子节点

//线段树#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cstdlib>#include<queue>#include<vector>#define LL long longusing namespace std;const int MAXN = 20000 + 5;const int INF = 1e9;int n,m,Ans = 0;inline void read(int &x){    x=0; int f=1; register char c = getchar();    while(c>'9'||c<'0'){ if(c=='-')f=-1; c=getchar(); }    while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); } x*=f;}struct Seg_Ment{    int s,t,id,p;// s、t线段端点 p是排序依据  id--排序之前的编号    Seg_Ment(int a,int b,int c,int d):s(a),t(b),p(c),id(d){}     Seg_Ment(){ s=t=p=id=0; }    bool operator < (const Seg_Ment a) const {        return p < a.p;    }}x[MAXN],y[MAXN];int lazy[MAXN << 3],cnt[MAXN << 3],l,r;inline void Push_Down(int u){    int ls = u << 1 ,rs = u << 1|1;    lazy[ls] += lazy[u],cnt[ls] += lazy[u],cnt[rs] += lazy[u],lazy[rs] += lazy[u];    lazy[u] = 0;}void UpDate(int u,int L,int R,int Del){    if(lazy[u]) Push_Down(u);    if(l <= L && R <= r){        cnt[u] += Del,lazy[u] += Del;    }    else if(L + 1 < R){        int Mid = (L+R) >>1,ls = u<<1,rs = u<<1|1;        if(l <= Mid && L <= r) UpDate(ls,L,Mid,Del);        if(r >= Mid && l <= R) UpDate(rs,Mid,R,Del);    }}int query(int u,int L,int R){    if(lazy[u]) Push_Down(u);    if(l <= L && R <= r && cnt[u] > 0) return R - L;    if(L + 1 < R){        int Mid = L+R >>1,a = 0,b = 0;        if(l <= Mid) a = query(u<<1,L,Mid);        if(r >= Mid) b = query(u<<1|1,Mid,R);        return a + b;    }    return 0;}#define Max 10001int main(int argc,char *argv[]){    int x1,y1,xx,yy;    read(n);    for(int i=1; i<=n; ++i){        read(x1),read(y1),read(xx),read(yy);        x1 += Max,xx += Max,y1 += Max, yy += Max;        x[i] = Seg_Ment(x1,xx,y1,i),y[i] = Seg_Ment(y1,yy,x1,i);        x[i + n] = Seg_Ment(x1,xx,yy,i + n),y[i + n] = Seg_Ment(y1,yy,xx,i + n);    }    sort(x + 1,x + 2 * n + 1);    sort(y + 1,y + 2 * n + 1);    memset(lazy,0,sizeof lazy ); memset(cnt,0,sizeof cnt );    for(int i=1; i<=n * 2; ++i){        l = x[i].s, r = x[i].t;        if(x[i].id <= n){            Ans += abs(r - l - query(1,1,MAXN));            UpDate(1,1,MAXN,1);        }        else {            UpDate(1,1,MAXN,-1);            Ans += abs(r - l - query(1,1,MAXN));        }    }    memset(lazy,0,sizeof lazy ); memset(cnt,0,sizeof cnt );    for(int i=1; i<=n * 2; ++i){        l = y[i].s,r = y[i].t;        if(y[i].id <= n){            Ans += abs(r - l - query(1,1,MAXN));            UpDate(1,1,MAXN,1);        }        else{            UpDate(1,1,MAXN,-1);            Ans += abs(r - l - query(1,1,MAXN));        }    }    cout << Ans << endl;    return 0;}
阅读全文
0 0