HDU - 3911 Black And White 区间翻转+区间连续最长
生活随笔
收集整理的這篇文章主要介紹了
HDU - 3911 Black And White 区间翻转+区间连续最长
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
區間翻轉的裸題,wrong了兩發,沒找bug,直接又打了一遍,這么大量的代碼找bug是瘋了。
重新開始做線段樹的一些題了,感覺對于pushdown與lazy數組有點印象了。
首先,lazy數組是記錄的當前數組的改變,不管是這個題的異或,還是加減,lazy數組就是線段樹的主要優化原因,當你用的時候你再下放,大大減少了復雜度。但是記錄的時候lazy[i]=1時候,tree[i]是要先處理的,然后每次每一查找的時候是先看該節點成不成立,不成立的話,再下放lazy。還有就是update的時候也要下放lazy.
就是這樣,這道題的話主要的問題就是區間反轉,lazy[i]變換兩次的話就是不變,所以用異或來處理剛剛好,區間連續最長的問題就是個模板,記錄左最長,右最長,總體最長。
1.在pushup的時候,要注意如果左兒子的左最長已經占了左邊的總長,那么父親節點的左最長就還要加上右兒子的左最長。
父節點的右最長也是相同的
tree[i].wl=tree[lson].wl+((tree[lson].wl==mid-l+1)?tree[rson].wl:0);
2.第二個問題就是在query的時候,找的是左兒子的總體最長,右兒子總體最長,以及左兒子的右最長+右兒子的左最長在詢問左端點ql,詢問右端點qr之間的總長度。
return max3(query(Lson,ql,mid),query(Rson,mid+1,qr),min(mid-ql+1,tree[lson].br)+min(qr-mid,tree[rson].bl));
結合全部代碼,用宏定義,寫起來會快很多還簡
潔,但是可能會慢一點,理解理解。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#define myself i,l,r
#define lson i<<1//左兒子
#define rson i<<1|1//右兒子
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define inff 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define me(a,b) memset(a,b,sizeof(a))
#define min4(a,b,c,d) min(min(a,b),min(c,d))
#define min3(x,y,z) min(min(x,y),min(y,z))
#define max4(a,b,c,d) max(max(a,b),max(c,d))
#define max3(x,y,z) max(max(x,y),max(y,z))
typedef long long ll;
using namespace std;
const int maxn=1e5+5;
struct node
{int wl,wr,wm,bl,br,bm;//w表示白的左,右,總;b就是black黑左右總
}tree[maxn<<2];
int lazy[maxn<<2];
int n,m;
void pushup(int i,int l,int r)//往上更新
{int mid=half;tree[i].wl=tree[lson].wl+((tree[lson].wl==mid-l+1)?tree[rson].wl:0);tree[i].bl=tree[lson].bl+((tree[lson].bl==mid-l+1)?tree[rson].bl:0);tree[i].wr=tree[rson].wr+((tree[rson].wr==r-mid)?tree[lson].wr:0);tree[i].br=tree[rson].br+((tree[rson].br==r-mid)?tree[lson].br:0);tree[i].wm=max3(tree[lson].wm,tree[rson].wm,tree[lson].wr+tree[rson].wl);tree[i].bm=max3(tree[lson].bm,tree[rson].bm,tree[lson].br+tree[rson].bl);
}
void change(int x)
{swap(tree[x].wl,tree[x].bl);swap(tree[x].wr,tree[x].br);swap(tree[x].wm,tree[x].bm);
}
void pushdown(int i,int l,int r)
{if(lazy[i]){lazy[lson]^=1;lazy[rson]^=1;change(lson);change(rson);lazy[i]=0;return;}
}
void update(int i,int l,int r,int ql,int qr)
{if(ql<=l&&qr>=r){change(i);lazy[i]^=1;return ;}int mid=half;pushdown(myself);if(qr<=mid) update(Lson,ql,qr);else if(ql>mid) update(Rson,ql,qr);else{update(Lson,ql,mid);update(Rson,mid+1,qr);}pushup(myself);
}
int query(int i,int l,int r,int ql,int qr)
{if(ql<=l&&qr>=r)return tree[i].bm;pushdown(myself);int mid=half;if(qr<=mid) return query(Lson,ql,qr);else if(ql>mid) return query(Rson,ql,qr);else return max3(query(Lson,ql,mid),query(Rson,mid+1,qr),min(mid-ql+1,tree[lson].br)+min(qr-mid,tree[rson].bl));
}
void build(int i,int l,int r)
{int x;lazy[i]=0;if(l==r){scanf("%d",&x);tree[i].bl=tree[i].br=tree[i].bm=x;tree[i].wl=tree[i].wr=tree[i].wm=x^1;return;}int mid=half;build(Lson);build(Rson);pushup(myself);
}
int main()
{int num,x,y;while(scanf("%d",&n)!=EOF){build(1,1,n);scanf("%d",&m);while(m--){scanf("%d%d%d",&num,&x,&y);if(num==0)printf("%d\n",query(1,1,n,x,y));elseupdate(1,1,n,x,y);}}return 0;
}
總結
以上是生活随笔為你收集整理的HDU - 3911 Black And White 区间翻转+区间连续最长的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU - 2586 How far a
- 下一篇: HDU - 3333 Turing Tr