题目链接:https://codeforces.com/gym/101982/attachments
要你求覆盖奇数次的矩形面积并,每次更新时减去原先的值即可实现奇数次有效,下推时为保证线段长度不变左儿子的值为x[mid]-x[l]再减原来的值,右儿子的值为x[r]-x[mid]再减原来的值
#include<iostream> #include<algorithm> using namespace std; #define ll long long #define maxn 200005 struct seg{ ll l,r,h,s; seg(){} seg(ll l,ll r,ll h,ll s):l(l),r(r),h(h),s(s){}; bool operator <(const seg &a)const{ return h<a.h; } }se[maxn]; ll sum[maxn<<2],lazy[maxn<<2],x[maxn]; void pushup(ll rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void pushdown(ll rt,ll l,ll r) { if(lazy[rt]) { lazy[rt<<1]^=1; lazy[rt<<1|1]^=1; ll mid=l+r>>1; sum[rt<<1]=x[mid]-x[l]-sum[rt<<1]; sum[rt<<1|1]=x[r]-x[mid]-sum[rt<<1|1]; lazy[rt]=0; } } void update(ll L,ll R,ll l,ll r,ll rt) { if(L<=l&&R>=r) { lazy[rt]^=1; sum[rt]=x[r]-x[l]-sum[rt]; return ; } ll mid=l+r>>1; pushdown(rt,l,r); if(L<mid)update(L,R,l,mid,rt<<1); //因为往右更新时是mid到r 不是mid+1到r 所以L<=mid 会造成死循环 如l=l r=2 L=2 R=3 mid=1 if(R>mid)update(L,R,mid,r,rt<<1|1); pushup(rt); } int main() { int n,x1,x2,y1,y2,tot=1; cin>>n; for(int i=1;i<=n;i++) { cin>>x1>>y1>>x2>>y2; x[tot]=x1; se[tot++]=seg(x1,x2,y1,1); x[tot]=x2; se[tot++]=seg(x1,x2,y2,-1); } x[0]=-1; sort(x+1,x+tot); sort(se+1,se+tot); int nx=unique(x,x+tot)-x; ll ans=0; for(int i=1;i<tot-1;i++) { ll l=lower_bound(x,x+nx,se[i].l)-x; ll r=lower_bound(x,x+nx,se[i].r)-x; update(l,r,1,nx,1); ans+=sum[1]*(se[i+1].h-se[i].h); } cout<<ans<<endl; return 0; }