題解 P3870 【[TJOI2009]開關】
阿新 • • 發佈:2019-02-17
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]開關】