1. 程式人生 > >題解 P3870 【[TJOI2009]開關】

題解 P3870 【[TJOI2009]開關】

odi 其中 輸出格式 spa 可能 告訴 max modify ()

這個題我楞是交了好幾遍沒有過......
後來@_皎月半灑花dalao告訴我說要^兒子節點的tag,然後就明白了......

行吧,先上題面:

題目描述

現有N(2 ≤ N ≤ 100000)盞燈排成一排,從左到右依次編號為:1,2,......,N。然後依次執行M(1 ≤ M ≤ 100000)項操作,操作分為兩種:第一種操作指定一個區間[a, b],然後改變編號在這個區間內的燈的狀態(把開著的燈關上,關著的燈打開),第二種操作是指定一個區間[a, b],要求你輸出這個區間內有多少盞燈是打開的。燈在初始時都是關著的。

輸入輸出格式

輸入格式:

第一行有兩個整數N和M,分別表示燈的數目和操作的數目。接下來有M行,每行有三個整數,依次為:c, a, b。其中c表示操作的種類,當c的值為0時,表示是第一種操作。當c的值為1時表示是第二種操作。a和b則分別表示了操作區間的左右邊界(1 ≤ a ≤ b ≤ N)。

輸出格式:

每當遇到第二種操作時,輸出一行,包含一個整數:此時在查詢的區間中打開的燈的數目。

這個題比較有好處的一點是有很多題都和這個題基本一樣。
然後我們看到這個題讓我們統計一個線段內的某一種和和修改區間:

線段樹啊!

然後我就把校門外的樹的代碼扒過來了......
評測記錄
後果:聽取WA聲一片。

為啥呢?

因為兒子節點有可能比父親節點提前改過了。
所以我們只能取反,把原先的狀態反過來。
然後就成了提交記錄

#include <iostream>
#include <cstdio>

using namespace std;
const int maxn=100001;
struct tree{
    int l,r,flash,dark;
    bool tag;
}segment[maxn<<2];
int n,m;

inline void update(int rt);
inline void pushdown(int rt);
inline void build_tree(int rt,int l,int r);
inline int query(int rt,int l,int r);
inline void modify(int rt,int l,int r);

int main()
{
    cin>>n>>m;
    build_tree(1,1,n);
    while (m--)
    {
        char flag;
        int l,r;
        cin>>flag>>l>>r;
        if (flag==‘0‘)modify(1,l,r);
        else cout<<query(1,l,r)<<‘\n‘;
    }
    return 0;
}

inline void update(int rt)
{
    int lson=rt<<1,rson=lson+1;
    segment[rt].flash=segment[lson].flash+segment[rson].flash;
    segment[rt].dark=segment[lson].dark+segment[rson].dark;
}
inline void pushdown(int rt)
{
    int lson=rt<<1,rson=lson+1;
    segment[lson].tag^=1;
    segment[rson].tag^=1;
    swap(segment[lson].dark,segment[lson].flash);
    swap(segment[rson].dark,segment[rson].flash);
    segment[rt].tag^=1;
}
inline void build_tree(int rt,int l,int r)
{
    segment[rt].l=l,segment[rt].r=r;
    if (l==r)
    {
        segment[rt].flash=0;
        segment[rt].dark=1;
        segment[rt].tag=false;
        return;
    }
    int mid=(r+l)>>1,lson=rt<<1,rson=lson+1;
    build_tree(lson,l,mid);
    build_tree(rson,mid+1,r);
    update(rt);
}
inline void modify(int rt,int l,int r)
{
    if (segment[rt].l<=l&&segment[rt].r>=r)
    {
        if (segment[rt].l==l&&segment[rt].r==r)
        {
            segment[rt].tag^=1;
            swap(segment[rt].flash,segment[rt].dark);
            return;
        }
        if (segment[rt].tag)pushdown(rt);
        int mid=(segment[rt].l+segment[rt].r)>>1,lson=rt<<1,rson=lson+1;
        if (r<=mid)modify(lson,l,r);
        else if (l>mid)modify(rson,l,r);
        else
        {
            modify(lson,l,mid);
            modify(rson,mid+1,r);
        }
        update(rt);
    }
    return ;
}
inline int query(int rt,int l,int r)
{
    if (segment[rt].l<=l&&segment[rt].r>=r)
    {
        if (segment[rt].l==l&&segment[rt].r==r)
        {
            return segment[rt].flash;
        }
        if (segment[rt].tag)pushdown(rt);
        int mid=(segment[rt].l+segment[rt].r)>>1,lson=rt<<1,rson=lson+1;
        if (r<=mid)return query(lson,l,r);
        else if (l>=mid+1)return query(rson,l,r);
        else return query(lson,l,mid)+query(rson,mid+1,r);
    }
    return 0;
}

行吧......

題解 P3870 【[TJOI2009]開關】