洛谷进阶版中此题的写法
查看原帖
洛谷进阶版中此题的写法
1435392
ZeroHead楼主2024/11/23 18:31

洛谷的进阶版书籍中只给出了make_tag的写法,今天刚学习了线段树,感觉很有意思,所以按照书中模版写了一个完整版,需要注意的是在pushdown中由于进行两次操作等的开关情况并不会变,所以在pushdown时要判断一下lazy-tag的奇偶

#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
const int MAXN=1e5+5;
int a[MAXN],w[MAXN*4],lzy[MAXN*4],n,m;
void pushup(const int u){
    w[u]=w[u*2]+w[u*2+1];
}
void build(const int u,int l,int r){
    if(l==r){
        w[u]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(u*2,l,mid);
    build(u*2+1,mid+1,r);
    pushup(u);
}
bool inrange(int L,int R,int l,int r){
    return l<=L && r>=R;
}
bool outofrange(int L,int R,int l,int r){
    return L>r || R<l;
}
void maketag(int u,int l,int r){
    lzy[u]^=1;
    w[u]=r-l+1-w[u];
}
void pushdown(int u,int l,int r){
    int mid=(l+r)>>1;
    if(lzy[u]) maketag(u*2,l,mid);
    if(lzy[u]) maketag(u*2+1,mid+1,r);
    lzy[u]=0;
}
int query(int u,int L,int R,int l,int r){
    if(inrange(L,R,l,r)) return w[u];
    else if(!outofrange(L,R,l,r)){
        int mid=(L+R)>>1;
        pushdown(u,L,R);
        return query(u*2,L,mid,l,r)+query(u*2+1,mid+1,R,l,r);
    }
    else return 0;
}
void update(int u,int L,int R,int l,int r){
    if(inrange(L,R,l,r)){
        maketag(u,L,R);
    }
    else if(!outofrange(L,R,l,r)){
        int mid=(L+R)>>1;
        pushdown(u,L,R);
        update(u*2,L,mid,l,r);
        update(u*2+1,mid+1,R,l,r);
        pushup(u);
    }
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    build(1,1,n);
    while(m--){
        int opt,x,y;
        cin>>opt>>x>>y;
        if(opt==0) update(1,1,n,x,y);
        else cout<<query(1,1,n,x,y)<<endl;
    }
    return 0;
}
2024/11/23 18:31
加载中...