题意:求n个矩形相交的周长和
思路:跟矩形面积并差不多,只是多了一些标记变量
shunum[num]用来标记这个区间被多少条线段覆盖(相当于此时有几根竖线,因为总区间被 shunum 条线段覆盖,那么必定有2*shunum的端点,这些端点其实就是连着竖线的)
len[num]区间被覆盖的长度
cnt[num]这个区间被覆盖了几次
ld,rd,是一个标记量,只有0,1,表示这个节点左右两个端点没有被覆盖,有为1,无为0(可用来判断是否重合,两条线相连只算 shunum ==1)
我调了好长时间一直不出样例,后面发现写的太快,把r-l+1硬是写成了l-r+1,而且这个错误超级难找!!太小的细节了~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#define lson l,mid,num<<1
#define rson mid+1,r,num<<1|1
using namespace std;
const int M=22222;
struct node
{
int l , r , h , flag;
node() {}
node(int x1,int x2,int y,int s):l(x1) , r(x2) , h(y) , flag(s) {}
bool operator < (const node &cmp) const
{
return h < cmp.h;
}
} line[M];
bool ld[M<<2],rd[M<<2];
int shunum[M<<2],cnt[M<<2],len[M<<2];
void PushUp(int num,int l,int r)
{
if (cnt[num])
{
ld[num] = rd[num] = 1;
len[num] = r - l + 1;//~~
shunum[num] = 2;
}
else if(l==r)
{
ld[num]=rd[num]=len[num]=shunum[num]=0;
}
else
{
ld[num]=ld[num<<1];
rd[num]=rd[num<<1|1];
len[num]=len[num<<1]+len[num<<1|1];
shunum[num]=shunum[num<<1]+shunum[num<<1|1];
if (ld[num<<1|1] && rd[num<<1]) shunum[num] -= 2;//两条线重合
}
}
void update(int L,int R,int flag,int l,int r,int num)
{
if(L<=l && r<=R)
{
cnt[num]+=flag;
PushUp(num,l,r);
return;
}
int mid=(l+r)>>1;
if(L<=mid)update(L,R,flag,lson);
if(R >mid)update(L,R,flag,rson);
PushUp(num,l,r);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
int lx=10000;
int rx=-10000;
int st=0;
while(n--)
{
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
lx=min(lx , x1);
rx=max(rx , x2);
line[st++] = node(x1,x2,y1,1);
line[st++] = node(x1,x2,y2,-1);
}
// cout<<lx<<" "<<rx<<endl;
sort(line,line+st);
int ans=0,Last=0;
for(int i=0; i<st; i++)
{
if(line[i].l<line[i].r)
if (line[i].l < line[i].r) update(line[i].l,line[i].r - 1,line[i].flag,lx,rx-1,1);
ans+=shunum[1]*(line[i+1].h-line[i].h);
ans+=abs(len[1]-Last);
Last=len[1];
}
printf("%d\n",ans);
}
return 0;
}