思路 懒标记法 记stop[rt] 表示 rt这个线段树节点的下方儿子们需要被更新几次 记住是下方 量纲不要乱 否则写的一堆渣代码
我的代码里面black是维护黑灯的数量 其实做烦了 如果是维护白灯数量更简单
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<vector> 5 #include<algorithm> 6 #define lson l,mid,rt<<1 7 #define rson mid+1,r,rt<<1|1 8 #define lrt rt<<1 9 #define rrt rt<<1|1 10 #define getmid int mid=(l+r)/2 11 using namespace std; 12 const int maxn=1100000; 13 14 int n,m,black[maxn*4],stop[maxn*4]; 15 16 void pushdown(int l,int r,int rt) 17 { 18 getmid; 19 stop[lrt]+=stop[rt]; 20 stop[rrt]+=stop[rt]; 21 if(stop[rt]%2==1) 22 { 23 black[lrt]=mid-l+1-black[lrt]; 24 black[rrt]=r-mid-black[rrt]; 25 } 26 stop[rt]=0; 27 } 28 29 30 void bud(int l,int r,int rt) 31 { 32 if(l==r) { 33 black[rt]=1; 34 return; 35 } 36 getmid; 37 bud(lson); 38 bud(rson); 39 black[rt]=black[lrt]+black[rrt]; 40 } 41 42 int query(int l,int r,int rt,int a,int b) 43 { 44 pushdown(l,r,rt); 45 if(a<=l && b>=r) 46 { 47 return black[rt]; 48 } 49 50 getmid; 51 int ans=0; 52 if(a<=mid) ans=query(lson,a,b); 53 if(b>mid) ans=ans+query(rson,a,b); 54 return ans; 55 } 56 57 void update(int l,int r,int rt,int a,int b) 58 { 59 pushdown(l,r,rt); 60 if(a<=l && b>=r) 61 { 62 black[rt]=r-l+1-black[rt]; 63 stop[rt]++; 64 return; 65 } 66 getmid; 67 if(a<=mid) {update(lson,a,b);} 68 if(b>mid) {update(rson,a,b);} 69 black[rt]=black[lrt]+black[rrt]; 70 } 71 72 73 int main() 74 { 75 //freopen("lites.in","r",stdin); 76 //freopen("lites.out","w",stdout); 77 scanf("%d%d",&n,&m); 78 bud(1,n,1); 79 80 81 for(int i=1,a,b,c;i<=m;i++) 82 { 83 scanf("%d%d%d",&a,&b,&c); 84 if(a==0) 85 { 86 update(1,n,1,b,c); 87 } 88 else 89 { 90 cout<<c-b+1-query(1,n,1,b,c)<<endl;; 91 } 92 } 93 94 95 96 return 0; 97 }