「CQOI2006」简单题 线段树

「CQOI2006」简单题 线段树

水。区间修改,单点查询。用线段树维护区间([L,R])内的所有(1)的个数,懒标记表示为当前区间是否需要反转(相对于区间当前状态),下方标记时懒标记取反即可。

#include <cstdio>
#include <cmath>
#define sl (x<<1)
#define sr (x<<1|1)
#define MAXN 100010
using namespace std;
struct nod{
    int l; int r;
    bool lazy; int val;
} tre[MAXN*4];
void buildt(int l, int r, int x){
    tre[x].l=l,tre[x].r=r;
    if(l==r){
        tre[x].val=0;
        return;
    }
    int mid=(l+r)>>1;
    buildt(l, mid, x<<1);
    buildt(mid+1, r, x<<1|1);
}
void push_down(int x){
    if(tre[x].lazy==0) return;
    tre[sl].lazy=!tre[sl].lazy;
    tre[sr].lazy=!tre[sr].lazy;
    if(tre[x].lazy) tre[sl].val=(tre[sl].r-tre[sl].l+1)-tre[sl].val;
    if(tre[x].lazy) tre[sr].val=(tre[sr].r-tre[sr].l+1)-tre[sr].val;
    tre[x].lazy=0;
}
void change(int x, int ql, int qr){
    if(ql<=tre[x].l&&tre[x].r<=qr){
        tre[x].val=tre[x].r-tre[x].l+1-tre[x].val;
        tre[x].lazy=!tre[x].lazy;
        return;
    }
    push_down(x);
    int mid=(tre[x].l+tre[x].r)>>1;
    if(ql<=mid) change(sl,ql,qr);
    if(qr>mid) change(sr,ql,qr);
    tre[x].val=tre[sl].val+tre[sr].val;
}
int query(int x, int q){
    if(tre[x].l==tre[x].r){
        return tre[x].val;
    }
    push_down(x);
    int mid=(tre[x].l+tre[x].r)>>1;
    int ans=0;
    if(q<=mid) ans=query(sl,q);
    else ans=query(sr,q);
    tre[x].val=tre[sl].val+tre[sr].val;
    return ans;
}
int n,m;
int main()
{
    scanf("%d %d", &n, &m);
    buildt(1,n,1);
    while(m--){
        int t;
        scanf("%d", &t);
        if(t==1){
            int l,r;
            scanf("%d %d", &l, &r);
            change(1,l,r);
        }else{
            int i;scanf("%d", &i);
            printf("%d
", query(1,i));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/santiego/p/11169991.html