zoukankan      html  css  js  c++  java
  • Hacker Cups and Balls Gym

    题目:题目链接

    题意:有编号从1到n的n个球和n个杯子. 每一个杯子里有一个球, 进行m次排序操作,每次操作给出l,r. 如果l<r,将[l,r]范围内的球按升序排序, 否则降序排, 问中间位置的数是多少.

    思路:

      暴力复杂度为m*nlog(n), 不能暴力排序

      二分答案, 对于当前mid, 我们将大于等于mid的数记为1, 否则记0, 则排序就是将某个区间的数改为1或0, 通过线段树区间更新可以方便的做到, 对排序后的结果查询判断二分区间应该取左还是取右, 若中间的数是1, 则说明答案大于等于当前的数, l右移, 否则左移

    AC代码:

      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 }
  • 相关阅读:
    包教包会之Open Live Writer设置代码样式
    走近Java之HashMap In JDK8
    走近Java之包装器类Integer
    走近Java之幕后的String
    一点心得
    一个简单的多线程代码实例
    C++实现快速排序
    力扣1025. 除数博弈
    力扣1721. 交换链表中的节点
    力扣1422. 分割字符串的最大得分
  • 原文地址:https://www.cnblogs.com/fan-jiaming/p/10328127.html
Copyright © 2011-2022 走看看