利用到的是,一条线段,只会出现两次。
那么,显然两次在线段树上遍历的节点是一样的,因此,我们可以直接修改定义,s u m [ c u r ] s u m [ c u r ] 表示线段树上的节点被多少条线段遍历到了,如果 s u m [ c u r ] > 0 s u m [ c u r ] > 0 ,显然 c u r c u r 的贡献即区间长度,否则呢?否则,我们不需要考虑更大的区间,因为更大的区间其一定会在深度更小的点算到,因此只需要将左右儿子的答案加起来即可。
那么,你想,对于一条线段加入、删除,其贡献都是对的,那么对于所有线段而言,显然也是对的了。
https://www.luogu.com.cn/problem/P9478
#include <bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int N=(int )(5e5 +5 );
struct node {
int pos,l,r,v;
node () {
pos=l=r=0 ;
}
node (int POS,int L,int R,int V) {
pos=POS; l=L; r=R; v=V;
}
}p[N*2 ];
struct nodex {
int x,y,xx,yy;
nodex () {
x=y=xx=yy=0 ;
}
nodex (int X,int Y,int XX,int YY) {
x=X; y=Y; xx=XX; yy=YY;
}
}xie[10 ];
struct Line {
int op,x,y,xx,yy;
Line () {
op=x=y=xx=yy=0 ;
}
Line (int OP,int X,int Y,int XX,int YY) {
op=OP; x=X; y=Y; xx=XX; yy=YY;
}
}L[N];
int Ltot;
bool vis[10 ];
int n,m,q,xtot,tot;
bool xiangli (int l,int r,int cl,int cr) {
if (r<cl) return 1 ;
if (cr<l) return 1 ;
return 0 ;
}
bool cmp (const node &x,const node &y) {
return x.pos==y.pos?x.v>y.v:x.pos<y.pos;
}
int ls[N*52 ],rs[N*52 ],len[N*52 ],sum[N*52 ],num,rt;
void push_up (int cur,int l,int r) {
if (sum[cur]>0 ) len[cur]=r-l+1 ;
else {
len[cur]=0 ;
if (ls[cur]) len[cur]+=len[ls[cur]];
if (rs[cur]) len[cur]+=len[rs[cur]];
}
}
void upt (int &cur,int l,int r,int cl,int cr,int v) {
if (!cur) cur=++num;
if (cl<=l&&r<=cr) {
sum[cur]+=v;
push_up (cur,l,r);
return ;
}
int mid=(l+r)>>1 ;
if (cl<=mid) upt (ls[cur],l,mid,cl,cr,v);
if (cr>mid) upt (rs[cur],mid+1 ,r,cl,cr,v);
push_up (cur,l,r);
}
signed main () {
cin.tie (0 ); ios::sync_with_stdio (false );
int c; cin>>c;
cin>>n>>m>>q;
for (int i=1 ;i<=q;i++) {
int op,x,y,xx,yy;
cin>>op>>x>>y>>xx>>yy;
if (op==1 ) {
L[++Ltot]=Line (op,x,y,xx,yy);
p[++tot]=node (x,y,y,1 );
p[++tot]=node (xx+1 ,y,y,-1 );
} else if (op==2 ) {
L[++Ltot]=Line (op,x,y,xx,yy);
p[++tot]=node (x,y,yy,1 );
p[++tot]=node (x+1 ,y,yy,-1 );
} else {
xie[++xtot]=nodex (x,y,xx,yy);
}
}
for (int i=1 ;i<=5 ;i++) {
for (int j=2 ;j<=xtot;j++) {
if (vis[j]) continue ;
for (int k=1 ;k<j;k++) {
if (vis[k]) continue ;
if (xie[k].y-xie[k].x==xie[j].y-xie[j].x) {
if (!xiangli (xie[k].x,xie[k].xx,xie[j].x,xie[j].xx)) {
vis[j]=1 ;
xie[k].x=min (xie[k].x,xie[j].x);
xie[k].xx=max (xie[k].xx,xie[j].xx);
xie[k].y=min (xie[k].y,xie[j].y);
xie[k].yy=max (xie[k].yy,xie[j].yy);
}
}
if (vis[j]) break ;
}
}
}
sort (p+1 ,p+1 +tot,cmp);
int ans=0 ;
for (int i=1 ;i<tot;i++) {
upt (rt,1 ,m,p[i].l,p[i].r,p[i].v);
ans+=(p[i+1 ].pos-p[i].pos)*len[rt];
}
for (int i=1 ;i<=xtot;i++) {
if (vis[i]) {
continue ;
}
map<int ,bool >mp; mp.clear ();
int res=xie[i].xx-xie[i].x+1 ;
for (int j=1 ;j<=Ltot;j++) {
if (L[j].op==1 ) {
int a=L[j].y-xie[i].y+xie[i].x;
if (L[j].x<=a&&a<=L[j].xx&&xie[i].x<=a&&a<=xie[i].xx) {
if (!mp.count (a)) mp[a]=1 ,--res;
}
} else {
int a=xie[i].y-xie[i].x+L[j].x;
if (L[j].y<=a&&a<=L[j].yy&&xie[i].y<=a&&a<=xie[i].yy) {
if (!mp.count (L[j].x)) mp[L[j].x]=1 ,--res;
}
}
}
ans+=res;
}
cout<<ans;
return 0 ;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2022-09-26 Codeforces Round #822 (Div. 2)