題目:題目連接ios
題意:有編號從1到n的n個球和n個杯子. 每個杯子裏有一個球, 進行m次排序操做,每次操做給出l,r. 若是l<r,將[l,r]範圍內的球按升序排序, 不然降序排, 問中間位置的數是多少.ui
思路:spa
暴力複雜度爲m*nlog(n), 不能暴力排序.net
二分答案, 對於當前mid, 咱們將大於等於mid的數記爲1, 不然記0, 則排序就是將某個區間的數改成1或0, 經過線段樹區間更新能夠方便的作到, 對排序後的結果查詢判斷二分區間應該取左仍是取右, 若中間的數是1, 則說明答案大於等於當前的數, l右移, 不然左移code
AC代碼:blog
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 #include <vector> 8 #include <string> 9 #include <map> 10 #include <set> 11 #include <unordered_map> 12 #include <unordered_set> 13 #include <queue> 14 #include <stack> 15 #include <list> 16 17 #define FRER() freopen("in.txt", "r", stdin) 18 #define FREW() freopen("out.txt", "w", stdout) 19 20 #define INF 0x3f3f3f3f 21 #define eps 1e-8 22 23 using namespace std; 24 25 const int maxn = 1e5 + 5; 26 27 int a[maxn], ql[maxn], qr[maxn], tree[maxn << 2], lazy[maxn << 2]; 28 29 void build(int l, int r, int rt, int num) { 30 lazy[rt] = 0; 31 if(l == r) { 32 tree[rt] = (a[l] >= num); 33 return ; 34 } 35 int m = (l + r) >> 1; 36 build(l, m, rt << 1, num); 37 build(m + 1, r, rt << 1|1, num); 38 tree[rt] = tree[rt << 1] + tree[rt << 1|1]; 39 } 40 41 void pushdown(int l, int r, int rt) { 42 int m = (l + r) >> 1; 43 lazy[rt << 1] = lazy[rt << 1|1] = lazy[rt]; 44 if(lazy[rt] == 1) { 45 tree[rt << 1|1] = min(tree[rt], r - m); 46 tree[rt << 1] = tree[rt] - tree[rt << 1|1]; 47 } 48 else if(lazy[rt] == 2){ 49 tree[rt << 1] = min(tree[rt], m - l + 1); 50 tree[rt << 1|1] = tree[rt] - tree[rt << 1]; 51 } 52 lazy[rt] = 0; 53 } 54 55 int querySum(int x, int y, int l, int r, int rt) { 56 if(x <= l && y >= r) return tree[rt]; 57 if(lazy[rt]) pushdown(l, r, rt); 58 int m = (l + r) >> 1, sum = 0; 59 if(x <= m) sum += querySum(x, y, l, m, rt << 1); 60 if(y > m) sum += querySum(x, y, m + 1, r, rt << 1|1); 61 return sum; 62 } 63 64 int query(int pos, int l, int r, int rt) { 65 if(l == r) return tree[rt]; 66 if(lazy[rt]) pushdown(l, r, rt); 67 int m = (l + r) >> 1; 68 if(pos <= m) return query(pos, l, m, rt << 1); 69 else return query(pos, m + 1, r, rt << 1|1); 70 } 71 72 void update(int x, int y, int l, int r, int rt, int flag, int sum) { 73 if(x <= l && y >= r) { 74 tree[rt] = sum; 75 lazy[rt] = flag; 76 return ; 77 } 78 if(lazy[rt]) pushdown(l, r, rt); 79 int m = (l + r) >> 1; 80 if(y <= m) update(x, y, l, m, rt << 1, flag, sum); 81 else if(x > m) update(x, y, m + 1, r, rt << 1|1, flag, sum); 82 else { 83 int lsum, rsum; 84 if(flag== 1) { 85 rsum = min(sum, y - m); 86 lsum = sum - rsum; 87 } 88 else if(flag == 2){ 89 lsum = min(sum, m - x + 1); 90 rsum = sum - lsum; 91 } 92 update(x, m, l, m, rt << 1, flag, lsum); 93 update(m + 1, y, m + 1, r, rt << 1|1, flag, rsum); 94 } 95 tree[rt] = tree[rt << 1] + tree[rt << 1|1]; 96 } 97 98 bool judge(int n, int m, int mid) { 99 build(1, n, 1, mid); 100 for(int i = 0; i < m; ++i) { 101 int sum = querySum(min(ql[i], qr[i]), max(ql[i], qr[i]), 1, n, 1); 102 if(ql[i] <= qr[i]) update(ql[i], qr[i], 1, n, 1, 1, sum); 103 else update(qr[i], ql[i], 1, n, 1, 2, sum); 104 } 105 return query((1 + n) >> 1, 1, n, 1); 106 } 107 108 int main() 109 { 110 //FRER(); 111 ios::sync_with_stdio(0); 112 cin.tie(0); 113 114 int n, m; 115 cin >> n >> m; 116 for(int i = 1; i <= n; ++i) cin >> a[i]; 117 for(int i = 0; i < m; ++i) cin >> ql[i] >> qr[i]; 118 int l = 1, r = n, ans; 119 while(l <= r) { 120 int mid = (l + r) >> 1; 121 if(judge(n, m, mid)) 122 ans = mid, l = mid + 1; 123 else r = mid - 1; 124 } 125 cout << ans << endl; 126 return 0; 127 }