[SHOI 2015] 腦洞治療儀
阿新 • • 發佈:2018-12-08
[題目連結]
https://www.lydsy.com/JudgeOnline/problem.php?id=4592
[演算法]
對於操作1 , 我們首先查詢區間[l0 , r0]中有多少個1 , 然後二分求出最大的x(x <= r1)使得[l1 , x]中0的個數 <= [l0 , r0]中1的個數
對於操作2 , 對於一段區間[l , r] , 我們將它分成[l , mid]和[mid + 1 , r]兩個子區間 , 那麼 , 最長連續的0的個數有三種情況 :
1. 在[l , mid]中 2. 在[mid + 1 , r]中 3. mid向前延伸最多的0的個數 + (mid + 1)向後延伸最多的0的個數
線段樹維護即可
時間複雜度 : O(NlogN ^ 2)
[程式碼]
#include<bits/stdc++.h> using namespace std; #define MAXN 200010 typedeflong long ll; typedef long double ld; const int inf = 1e9; int n , m; template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); } template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); } template <typename T> inline void read(T &x) { T f= 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } struct Segment_Tree { struct Node { int l , r; int lm0 , rm0 , value , cnt; int tag; } a[MAXN << 2]; inline void build(int index , int l , int r) { a[index].l = l , a[index].r = r; a[index].cnt = r - l + 1; a[index].tag = -1; if (l == r) return; int mid = (l + r) >> 1; build(index << 1 , l , mid); build(index << 1 | 1 , mid + 1 , r); } inline void update(int x) { int l = a[x].l , r = a[x].r; int mid = (l + r) >> 1; a[x].cnt = a[x << 1].cnt + a[x << 1 | 1].cnt; if (a[x << 1].lm0 == mid - l + 1) a[x].lm0 = mid - l + 1 + a[x << 1 | 1].lm0; else a[x].lm0 = a[x << 1].lm0; if (a[x << 1 | 1].rm0 == r - mid) a[x].rm0 = r - mid + a[x << 1].rm0; else a[x].rm0 = a[x << 1 | 1].rm0; a[x].value = max(a[x << 1].value , a[x << 1 | 1].value); chkmax(a[x].value , a[x << 1].rm0 + a[x << 1 | 1].lm0); } inline void pushdown(int index) { int l = a[index].l , r = a[index].r; int mid = (l + r) >> 1; if (l == r) return; if (a[index].tag == 0) { a[index << 1].cnt = a[index << 1 | 1].cnt = 0; a[index << 1].value = mid - l + 1; a[index << 1 | 1].value = r - mid; a[index << 1].lm0 = a[index << 1].rm0 = mid - l + 1; a[index << 1 | 1].lm0 = a[index << 1 | 1].rm0 = r - mid; a[index << 1].tag = a[index << 1 | 1].tag = a[index].tag; a[index].tag = -1; } if (a[index].tag == 1) { a[index << 1].cnt = mid - l + 1; a[index << 1 | 1].cnt = r - mid; a[index << 1].value = a[index << 1 | 1].value = 0; a[index << 1].lm0 = a[index << 1].rm0 = 0; a[index << 1 | 1].lm0 = a[index << 1 | 1].rm0 = 0; a[index << 1].tag = a[index << 1 | 1].tag = a[index].tag; a[index].tag = -1; } } inline void modify(int index , int l , int r) { if (a[index].l == l && a[index].r == r) { a[index].cnt = 0; a[index].lm0 = a[index].rm0 = r - l + 1; a[index].value = r - l + 1; a[index].tag = 0; return; } pushdown(index); int mid = (a[index].l + a[index].r) >> 1; if (mid >= r) modify(index << 1 , l , r); else if (mid + 1 <= l) modify(index << 1 | 1 , l , r); else { modify(index << 1 , l , mid); modify(index << 1 | 1 , mid + 1 , r); } update(index); } inline int queryA(int index , int l , int r) { if (a[index].l == l && a[index].r == r) return a[index].cnt; pushdown(index); int mid = (a[index].l + a[index].r) >> 1; if (mid >= r) return queryA(index << 1 , l , r); else if (mid + 1 <= l) return queryA(index << 1 | 1 , l , r); else return queryA(index << 1 , l , mid) + queryA(index << 1 | 1 , mid + 1 , r); } inline int queryB(int index , int l , int r) { if (a[index].l == l && a[index].r == r) return a[index].value; pushdown(index); int mid = (a[index].l + a[index].r) >> 1; if (mid >= r) return queryB(index << 1 , l , r); else if (mid + 1 <= l) return queryB(index << 1 | 1 , l , r); { int ret = max(queryB(index << 1 , l , mid) , queryB(index << 1 | 1 , mid + 1 , r)); chkmax(ret , min(mid - l + 1 , a[index << 1].rm0) + min(r - mid , a[index << 1 | 1].lm0)); return ret; } } inline void change(int index , int l , int r) { if (l > r) return; if (a[index].l == l && a[index].r == r) { a[index].cnt = r - l + 1; a[index].lm0 = a[index].rm0 = a[index].value = 0; a[index].tag = 1; return; } pushdown(index); int mid = (a[index].l + a[index].r) >> 1; if (mid >= r) change(index << 1 , l , r); else if (mid + 1 <= l) change(index << 1 | 1 , l , r); else { change(index << 1 , l , mid); change(index << 1 | 1 , mid + 1 , r); } update(index); } } SGT; int main() { read(n); read(m); SGT.build(1 , 1 , n); for (int i = 1; i <= m; i++) { int type; read(type); if (type == 0) { int x , y; read(x); read(y); SGT.modify(1 , x , y); } else if (type == 1) { int l0 , r0 , l1 , r1; read(l0); read(r0); read(l1); read(r1); int cnt = SGT.queryA(1 , l0 , r0); SGT.modify(1 , l0 , r0); int l = l1 , r = r1 , loc = 0; while (l <= r) { int mid = (l + r) >> 1; if ((mid - l1 + 1) - SGT.queryA(1 , l1 , mid) <= cnt) { loc = mid; l = mid + 1; } else r = mid - 1; } SGT.change(1 , l1 , loc); } else { int l , r; read(l); read(r); printf("%d\n" , SGT.queryB(1 , l , r)); } } return 0; }