一、矩阵面积并 (HDU 1542)

#include<bits/stdc++.h>
#define N 2010
using namespace std;

struct seg
{
    int l,r,h,d;
    seg(){}
    seg(int l,int r,int h,int d):l(l),r(r),h(h),d(d){}
    bool operator < (const seg a)const{return h<a.h;}
}a[N];

int i,j,k,l,n,m,t,h;
int c[N<<1],sum[N<<2],cnt[N<<2];

void push_up(int x,int l,int r)
{
    if (cnt[x])sum[x]=c[r+1]-c[l];else
    if (l==r)sum[x]=0;else
    sum[x]=sum[x<<1]+sum[x<<1|1];
}

void updata(int x,int l,int r,int fl,int fr,int v)
{
    if (fl<=l && r<=fr)
    {
        cnt[x]+=v;
        push_up(x,l,r);
        return;
    }
    int t=(l+r)>>1;
    if (fl<=t)updata(x<<1,l,t,fl,fr,v);
    if (fr>t)updata(x<<1|1,t+1,r,fl,fr,v);
    push_up(x,l,r);
}

int main()
{
    int x,y,xx,yy;
    while (~scanf("%d",&n) && n)
    {
        for (i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&x,&y,&xx,&yy);
            a[i]=seg(x,xx,y,1);
            a[i+n]=seg(x,xx,yy,-1);
            c[i]=x;c[i+n]=xx;
        }
        n<<=1;
        sort(a+1,a+1+n);
        sort(c+1,c+1+n);
        m=unique(c+1,c+n+1)-c-1;
        int ans=0;
        memset(sum,0,sizeof sum);
        memset(cnt,0,sizeof cnt);
        for (i=1;i<n;i++)
        {
            int fl=lower_bound(c+1,c+m+1,a[i].l)-c,fr=lower_bound(c+1,c+m+1,a[i].r)-c;
            if (fl<fr)updata(1,1,m,fl,fr-1,a[i].d);
            ans+=sum[1]*(a[i+1].h-a[i].h);
        }
        printf("%d\n",ans);
    }
    puts("*");
}

二、矩阵周长并(HDU 1828)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 5010
#define MAX 10100
#define lch(i) ((i)<<1)
#define rch(i) ((i)<<1|1)

struct segment
{
    int l,r,h,v;
}s[2*N];

struct node
{
    int l,r,lp,rp,cnt,len,num;
    int mid()
    { return (l+r)>>1; }
}t[2*MAX*4];

int cmp(struct segment p ,struct segment q)
{
    return p.h<q.h;
}

void build(int l ,int r, int rt)
{
    t[rt].l=l; t[rt].r=r;
    t[rt].cnt=t[rt].len=0;
    t[rt].lp=t[rt].rp=t[rt].num=0;
    if(l==r) return ;
    int mid=t[rt].mid();
    build(l,mid,lch(rt));
    build(mid+1,r,rch(rt));
}

void cal(int rt)
{
    if(t[rt].cnt)
    {
        t[rt].len=t[rt].r-t[rt].l+1;
        t[rt].lp=t[rt].rp=1;
        t[rt].num=1;
    }
    else if(t[rt].l == t[rt].r) //叶子
    {
        t[rt].len=0;
        t[rt].lp=t[rt].rp=0;
        t[rt].num=0;
    }
    else
    {
        t[rt].len=t[lch(rt)].len+t[rch(rt)].len;
        t[rt].lp=t[lch(rt)].lp; 
        t[rt].rp=t[rch(rt)].rp;
        t[rt].num=t[lch(rt)].num + t[rch(rt)].num - (t[lch(rt)].rp&t[rch(rt)].lp);
    }
}

void updata(int l ,int r ,int v ,int rt)
{
    if(t[rt].l==l && t[rt].r==r) //目标区间
    {
        t[rt].cnt += v;
        cal(rt);
        return ;
    }
    int mid=t[rt].mid();
    if(r<=mid)     updata(l,r,v,lch(rt));
    else if(l>mid) updata(l,r,v,rch(rt));
    else
    {
        updata(l,mid,v,lch(rt));
        updata(mid+1,r,v,rch(rt));
    }
    cal(rt);
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0) 
        { puts("0"); continue; }
        int i,maxx,minx,m;
        for(i=0,m=0,maxx=-MAX,minx=MAX; i<n; i++,m+=2)
        {
            int x1,y1,x2,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            maxx=max(maxx,x2);
            minx=min(minx,x1);
            s[m].l=x1;   s[m].r=x2;   s[m].h=y1;   s[m].v=1;
            s[m+1].l=x1; s[m+1].r=x2; s[m+1].h=y2; s[m+1].v=-1;
        }
        sort(s,s+m,cmp);
        build(minx,maxx-1,1);
        int res=0 , prelen=0;
        s[m]=s[m-1]; //每次处理循环的最后一次
        for(int i=0; i<m; i++)
        {
            updata(s[i].l,s[i].r-1,s[i].v,1);
            res += abs(t[1].len-prelen); //计算横线部分
            res += (s[i+1].h-s[i].h)*(2*t[1].num); //计算竖线部分
            prelen=t[1].len;
        }
        printf("%d\n",res);
    }
    return 0;
}