甚至开N<<3也要RE...
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
struct node
{
//类似标记永久化,但有一定不同
int sum;//sum表示这个区间内被截取的长度
int cover;//cover优先级比sum高,表示该区间被完全覆盖的次数
}seg[N<<4];
struct line
{
int l,r;
int y;
int op;//op=1表示添加,op=-1表示删除
};
int n;
int res=0;
int xx1,yy1,xx2,yy2;
map<int,int>mpx;
vector<int>allx;
vector<line>all_lines;
inline bool it(line m1,line m2)
{
return m1.y<m2.y;
}
inline void Pushup(int root,int L,int R)
{
//计算时,区间为[L,R],则所得的长度为allx[R+1]-allx[L]
if(seg[root].cover)seg[root].sum=allx[R+1]-allx[L];//如果本区间有cover标记,则本区间的覆盖长度即为该区间长度
else seg[root].sum=seg[root<<1].sum+seg[root<<1|1].sum;//如果没有的话,则本区间的覆盖长度为两个子区间长度相加
}
inline void Modify(int l,int r,int L,int R,int root,int c)
{
if(L>r||R<l)return;
if(L>=l&&R<=r){seg[root].cover+=c;Pushup(root,L,R);return;}//注意这里需要Pushup
int mid=L+R>>1;
Modify(l,r,L,mid,root<<1,c);
Modify(l,r,mid+1,R,root<<1|1,c);
Pushup(root,L,R);
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
//离线操作+离散化
for(int i=1;i<=n;i++)
{
cin>>xx1>>yy1>>xx2>>yy2;
if(xx1>xx2)swap(xx1,xx2);
if(yy1>yy2)swap(yy1,yy2);
mpx[xx1]=0,mpx[xx2]=0;
all_lines.push_back({xx1,xx2,yy1,1});
all_lines.push_back({xx1,xx2,yy2,-1});
}
allx.push_back(-1e10);
int cnt=0;//cnt表示总节点数
for(auto [i,j]:mpx){allx.push_back(i);mpx[i]=++cnt;}
sort(allx.begin(),allx.end());
sort(all_lines.begin(),all_lines.end(),it);//对所有横向边按照y排序
//映射线段时,如果两端点分别为L,R,则映射到[L,R-1]上
Modify(mpx[all_lines[0].l],mpx[all_lines[0].r]-1,1,cnt-1,1,all_lines[0].op);//先把一开始的那条线段处理好
for(int i=1;i<all_lines.size();i++)//先计算上面的结果再Modify,这里的all_lines.size()相当于n*2
{
res+=(all_lines[i].y-all_lines[i-1].y)*seg[1].sum;
Modify(mpx[all_lines[i].l],mpx[all_lines[i].r]-1,1,cnt-1,1,all_lines[i].op);
}
cout<<res;
return 0;
}