BZOJ 4552 [Tjoi2016&Heoi2016]排序
阿新 • • 發佈:2018-06-16
HR 降序排序 二分 update for 進行 %d center OS
Submit: 2035 Solved: 1015
[Submit][Status][Discuss]
位置上的數字。
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3
4552: [Tjoi2016&Heoi2016]排序
Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2035 Solved: 1015
[Submit][Status][Discuss]
Description
在2016年,佳媛姐姐喜歡上了數字序列。因而他經常研究關於序列的一些奇奇怪怪的問題,現在他在研究一個難題 ,需要你來幫助他。這個難題是這樣子的:給出一個1到n的全排列,現在對這個全排列序列進行m次局部排序,排 序分為兩種:1:(0,l,r)表示將區間[l,r]的數字升序排序2:(1,l,r)表示將區間[l,r]的數字降序排序最後詢問第qInput
輸入數據的第一行為兩個整數n和m。n表示序列的長度,m表示局部排序的次數。1 <= n, m <= 10^5第二行為n個整 數,表示1到n的一個全排列。接下來輸入m行,每一行有三個整數op, l, r, op為0代表升序排序,op為1代表降序 排序, l, r 表示排序的區間。最後輸入一個整數q,q表示排序完之後詢問的位置, 1 <= q <= n。1 <= n <= 10^5 ,1 <= m <= 10^5Output
輸出數據僅有一行,一個整數,表示按照順序將全部的部分排序結束後第q位置上的數字。
Sample Input
6 31 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3
Sample Output
5 總結: 考慮二分答案,將問題轉化為判定性問題 可以發現,我們不好直接排序,但是如果是01串,就可以用線段樹維護排序 詢問只有一組q,於是二分最後的答案(mid) 將原數組中大於mid的設為0,小於等於mid的設為1,建立線段樹 然後每次排序,相當於對01串進行排序 最後查詢q位置的數,如果為1,則ans = mid, r = mid - 1否則l = mid + 1#include <bits/stdc++.h> using namespace std; const int maxn = 4e5 + 7; int sum[maxn], tag[maxn], a[maxn], n; struct Node { int op, l, r; } q[maxn]; int Q, m; void update(int o) { sum[o] = sum[o << 1] + sum[o << 1 | 1]; } void pushdown(int o, int l, int r) { if(tag[o] != -1) { int mid = (l + r) >> 1; tag[o << 1] = tag[o]; tag[o << 1 | 1] = tag[o]; sum[o << 1] = tag[o] * (mid - l + 1); sum[o << 1 | 1] = tag[o] * (r - mid); tag[o] = -1; } } int Query(int o, int l, int r, int ql, int qr) { if(ql <= l && r <= qr) return sum[o]; int mid = (l + r) >> 1; pushdown(o, l, r); int res = 0; if(ql <= mid) res += Query(o << 1, l, mid, ql, qr); if(qr > mid) res += Query(o << 1 | 1, mid + 1, r, ql, qr); return res; } void Modify(int o, int l, int r, int ql, int qr, int z) { if(ql <= l && r <= qr) { sum[o] = z * (r - l + 1); tag[o] = z; return; } int mid = (l + r) >> 1; pushdown(o, l, r); if(ql <= mid) Modify(o << 1, l, mid, ql, qr, z); if(qr > mid) Modify(o << 1 | 1, mid + 1, r, ql, qr, z); update(o); } void Build(int o, int l, int r, int x) { tag[o] = -1; if(l == r) { sum[o] = (a[l] <= x); return; } int mid = (l + r) >> 1; Build(o << 1, l, mid, x); Build(o << 1 | 1, mid + 1, r, x); update(o); } bool check(int x) { Build(1, 1, n, x); for (int i = 1; i <= m; ++i) { int res = Query(1, 1, n, q[i].l, q[i].r); if(res == 0 || res == (q[i].r - q[i].l + 1)) continue; if(!q[i].op) { Modify(1, 1, n, q[i].l, q[i].l + res - 1, 1); Modify(1, 1, n, q[i].l + res, q[i].r, 0); } else { Modify(1, 1, n, q[i].r - res + 1, q[i].r, 1); Modify(1, 1, n, q[i].l, q[i].r - res, 0); } } return Query(1, 1, n, Q, Q); } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 1; i <= m; ++i) scanf("%d%d%d", &q[i].op, &q[i].l, &q[i].r); int l = 1, r = n, ans = 0; scanf("%d", &Q); while(l <= r) { int mid = (l + r) >> 1; if(check(mid)) { ans = mid; r = mid - 1; } else l = mid + 1; } printf("%d\n", ans); return 0; }
BZOJ 4552 [Tjoi2016&Heoi2016]排序