题解 P3870 【[TJOI2009]开关】

· · 题解

又是一道线段树。。。

本题其实是一道裸题。。。不明白为什么是这个难度标签。

思路很明显,用tree[i].val表示区间内开着的灯的数量。

然后常规操作(建树、查询、修改)就可以了。

最后:lazy tag是个好东西。

#include <iostream>
#include <cstdio>
#include <algorithm>
#define lson pos << 1
#define rson pos << 1 | 1
using namespace std;

const int maxn = 100100;

int n, m, c, a, b;

struct node {
    int l,r;
    int val;          
    int lazy;
} tree[maxn << 2];

inline void Pushup(int pos) {
    tree[pos].val = tree[lson].val + tree[rson].val;
}

void Pushdown(int pos) {
    if(tree[pos].lazy) {
        tree[lson].lazy ^= 1; 
        tree[rson].lazy ^= 1;
        tree[lson].val = tree[lson].len() - tree[lson].val;
        tree[rson].val = tree[rson].len() - tree[rson].val;
        tree[pos].lazy = 0;
    }
}

void Build(int l, int r, int pos) {  
    tree[pos].l = l;
    tree[pos].r = r;
    tree[pos].val = 0;
    if(l == r) return ;
    int mid = (l + r) >> 1;
    Build(l, mid, lson);
    Build(mid + 1, r, rson);
}

void Update(int l, int r, int pos) {
    if(l <= tree[pos].l && tree[pos].r <= r) {
        tree[pos].val = tree[pos].len() - tree[pos].val;
        tree[pos].lazy ^= 1;
        return ;
    }
    Pushdown(pos);
    int mid = tree[pos].mid();
    if(l <= mid) Update(l, r, lson);
    if(r > mid) Update(l, r, rson);
    Pushup(pos);
}

int Query(int l, int r, int pos) {
    if(l <= tree[pos].l && tree[pos].r <= r) {
        return tree[pos].val;
    }
    Pushdown(pos);
    int mid = tree[pos].mid();
    int ans = 0;
    if(l <= mid)  ans += Query(l, r, lson);
    if(r > mid)   ans += Query(l, r, rson);
    return ans;
}

int main() {
    cin >> n >> m;
    Build(1, n, 1);
    while(m--) {
        cin >> c >> a >> b;
        if(c == 0) {
            Update(a, b, 1);
        } else {
            cout << Query(a, b, 1) << endl;
        }
    }
}

话说回来。。。这道题好像在洛谷上有不知一道重题,可以n倍经验了!!