1. 程式人生 > 其它 >洛谷P2574 XOR的藝術 題解

洛谷P2574 XOR的藝術 題解

技術標籤:資料結構leetcode演算法pythonc++

XOR的藝術 - 洛谷

description:

給定一個長度為

n0/1 串,有區間反轉 0\rightarrow1,1\rightarrow0 和區間求和兩種操作。輸出每次的區間和。
  • n\le 2 \times 10^5

solution:

顯然是一道線段樹區間修改區間查詢的題目。

區間查詢相比於模板題一點變化都沒有,唯一的難點在區間修改。

我們記錄一個區間內

1 的個數,也就是區間和。

可以發現,當一個區間反轉時,只需要用區間長度減去區間和即可得到新的區間和。

而且,這在父子節點中也具有傳遞性。


code:

#include<cstdio>
using namespace
std; struct ben { long long l,r,sum,lazy; }tree[800005]; long long a[200005]; void build(long long l,long long r,long long id) { tree[id].l=l; tree[id].r=r; if(tree[id].l==tree[id].r) { tree[id].sum=a[l]; return ; } long long mid=(tree[id].l+tree[id].r)/2; build(l,mid,id*2); build(mid+1,r,id*2+
1); tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; } void down(long long id) { tree[id*2].sum=tree[id*2].r-tree[id*2].l+1-tree[id*2].sum; tree[id*2].lazy=!tree[id*2].lazy; tree[id*2+1].sum=tree[id*2+1].r-tree[id*2+1].l+1-tree[id*2+1].sum; tree[id*2+1].lazy=!tree[id*2+1].lazy; tree[id].lazy=0; }
void qujianjia(long long id,long long l,long long r) { if(tree[id].l>=l&&tree[id].r<=r) { long long tmp=tree[id].sum; tree[id].sum=tree[id].r-tree[id].l+1-tree[id].sum; tree[id].lazy=!tree[id].lazy; return ; } if(tree[id].lazy)down(id); long long mid=(tree[id].l+tree[id].r)/2; if(mid>=l) { qujianjia(id*2,l,r); } if(mid<r) { qujianjia(id*2+1,l,r); } tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; } long long ans; void qujianhe(long long id,long long l,long long r) { if(tree[id].l>=l&&tree[id].r<=r) { ans+=tree[id].sum; return; } if(tree[id].lazy)down(id); long long mid=(tree[id].l+tree[id].r)/2; if(mid>=l) { qujianhe(id*2,l,r); } if(mid<r) { qujianhe(id*2+1,l,r); } } int main() { long long n,m; scanf("%lld%lld",&n,&m); for(long long i=1;i<=n;i++) { scanf("%1lld",&a[i]); } build(1,n,1); while(m--) { long long op,x,y,k; scanf("%lld%lld%lld",&op,&x,&y); if(op==0) { //scanf("%lld",&k); qujianjia(1,x,y); } if(op==1) { ans=0; qujianhe(1,x,y); printf("%lld\n",ans); } } return 0; }