标签:node typedef 次数 int 的区别 class line clu 线段树

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=2e5+10; //因为一个矩形有两边所以数据范围要乘2
int y[maxn];
struct L
{
int x; //竖边的x坐标
int y1,y2; //竖边的y坐标,y1较小
int state; //是左边还是右边
bool operator<(const L &b)const //排序时使用x坐标排序
{
return x<b.x;
}
} line[maxn];
struct node //线段树
{
int l,r; //结点区间左右
int cover; //被覆盖次数
ll len; //区间真实长度
} sgt[maxn<<3]; //注意这个大小
inline void pushup(int k) //与普通线段树的区别
{
if (sgt[k].cover)
{
sgt[k].len=sgt[k].r-sgt[k].l;
}
else
{
sgt[k].len=sgt[k<<1].len+sgt[k<<1|1].len;
}
}
void build (int rt,int l,int r)
{
sgt[rt].l=y[l];
sgt[rt].r=y[r]; //与普通线段树的区别
if (r-l<=1) return; //与普通线段树的区别
int mid=(r+l)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid,r);
}
void update(int rt,int x,int y,int z)
{
int l=sgt[rt].l,r=sgt[rt].r;
if (x<=l&&r<=y)
{
sgt[rt].cover+=z;
pushup(rt);
return;
}
if (x<sgt[rt<<1].r) update(rt<<1,x,y,z); //与普通线段树的区别
if (y>sgt[rt<<1|1].l) update(rt<<1|1,x,y,z); //与普通线段树的区别
pushup(rt);
}
int main()
{
int n;
scanf("%d",&n);
for (int i=1,x1,x2,y1,y2; i<=n; i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
y[i]=y1;
y[i+n]=y2;
line[i]=L{x1,y1,y2,1};
line[i+n]=L{x2,y1,y2,-1};
}
line[0].x=0;
sort(y+1,y+1+n*2);
sort(line+1,line+n*2+1);
build (1,1,n<<1);
ull ans=0; //爆int的毒瘤数据只好用ull处理
for (int i=1; i<=n<<1; i++)
{
ans+=1ull*sgt[1].len*(line[i].x-line[i-1].x);
update(1,line[i].y1,line[i].y2,line[i].state);
}
printf("%llu\n",ans);
return 0;
}
标签:node typedef 次数 int 的区别 class line clu 线段树
原文地址:https://www.cnblogs.com/Accpted/p/11367422.html