zoukankan      html  css  js  c++  java
  • 【BZOJ4552】【HEOI2016】排序 [二分答案][线段树]

    排序

    Time Limit: 60 Sec  Memory Limit: 256 MB
    [Submit][Status][Discuss]

    Description

      在2016年,佳媛姐姐喜欢上了数字序列。
      因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。
      这个难题是这样子的:
      给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:
        1: (0,l,r)表示将区间[l,r]的数字升序排序
        2: (1,l,r)表示将区间[l,r]的数字降序排序
      最后询问第q位置上的数字。

    Input

      输入数据的第一行为两个整数n和m。
      n表示序列的长度,m表示局部排序的次数。
      第二行为n个整数,表示1到n的一个全排列。
      接下来输入m行,每一行有三个整数op, l, r,
       op为0代表升序排序,op为1代表降序排序, l, r 表示排序的区间。
      最后输入一个整数q,q表示排序完之后询问的位置。

    Output

      输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。

    Sample Input

      6 3
      1 6 2 5 3 4
      0 1 4
      1 3 6
      0 2 4
      3

    Sample Output

      5

    HINT

      1 <= n <= 10^5,1 <= m <= 10^5, 1 <= q <= n。

    Solution

      我们先考虑如果权值很小的话怎么做,显然可以对每个权值开一个线段树维护在哪些位置出现过。

      那么排序显然就是覆盖连续的一段。只要知道某一区间有几个这个权值即可。

      但是这样显然是过不了的,于是我们考虑二分答案,把val >= mid的设为1,其余的设为0

      这样就把权值变成了0/1,那么显然我们按照以上操作,如果Q位置上是1说明mid<=Ans还可以更大一点否则说明mid>Ans

      只要支持区间求和以及区间覆盖0/1即可。

    Code

      1 #include<iostream>
      2 #include<string>
      3 #include<algorithm>
      4 #include<cstdio>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cmath>
      8 using namespace std;
      9 typedef long long s64;
     10  
     11 const int ONE = 400005;
     12 const int MOD = 1e9 + 7;
     13  
     14 int get()
     15 {
     16         int res = 1, Q = 1; char c;
     17         while( (c = getchar()) < 48 || c > 57)
     18             if(c == '-') Q = -1;
     19         if(Q) res = c - 48;
     20         while( (c = getchar()) >= 48 && c <= 57)
     21             res = res * 10 + c - 48;
     22         return res * Q;
     23 }
     24  
     25 int n, m, Q;
     26 int a[ONE];
     27 int res, now;
     28  
     29 struct power
     30 {
     31         struct point
     32         {
     33             int val, tag;
     34         }Node[ONE];
     35  
     36         void Build(int i, int l, int r)
     37         {
     38             Node[i].tag = -1;
     39             if(l == r) return;
     40             int mid = l + r >> 1;
     41             Build(i << 1, l, mid);
     42             Build(i << 1 | 1, mid + 1, r);
     43         }
     44  
     45         int pushdown(int i, int l, int r)
     46         {
     47             int mid = l + r >> 1;
     48             if(Node[i].tag != -1)
     49             {
     50                 Node[i << 1].tag = Node[i].tag;
     51                 Node[i << 1].val = Node[i].tag * (mid - l + 1);
     52                 Node[i << 1 | 1].tag = Node[i].tag;
     53                 Node[i << 1 | 1].val = Node[i].tag * (r - (mid + 1) + 1);
     54                 Node[i].tag = -1;
     55             }
     56         }
     57  
     58         void Update(int i, int l, int r, int L, int R, int x)
     59         {
     60             if(L > R) return;
     61             if(L <= l && r <= R)
     62             {
     63                 Node[i].tag = x;
     64                 Node[i].val = x * (r - l + 1);
     65                 return;
     66             }
     67             pushdown(i, l, r);
     68             int mid = l + r >> 1;
     69             if(L <= mid) Update(i << 1, l, mid, L, R, x);
     70             if(mid + 1 <= R) Update(i << 1 | 1, mid + 1, r, L, R, x);
     71             Node[i].val = Node[i << 1].val + Node[i << 1 | 1].val;
     72         }
     73  
     74         void Query(int i, int l, int r, int L, int R)
     75         {
     76             if(L > R) return;
     77             if(L <= l && r <= R)
     78             {
     79                 res += Node[i].val;
     80                 return;
     81             }
     82             pushdown(i, l, r);
     83             int mid = l + r >> 1;
     84             if(L <= mid) Query(i << 1, l, mid, L, R);
     85             if(mid + 1 <= R) Query(i << 1 | 1, mid + 1, r, L, R);
     86         }
     87 }C[2];
     88  
     89 struct operate
     90 {
     91         int l, r, x;
     92 }oper[ONE];
     93  
     94 void Modify(int id, int Left, int Right)
     95 {
     96         res = 0;
     97         C[id].Query(1, 1, n, Left, Right);
     98         C[id].Update(1, 1, n, Left, Right, 0);
     99         C[id].Update(1, 1, n, now, now + res - 1, 1);
    100         now += res;
    101 }
    102  
    103 int Check(int mid)
    104 {
    105         for(int i = 0; i <= 1; i++)
    106             C[i].Node[1].tag = 0;
    107  
    108         for(int i = 1; i <= n; i++)
    109             C[a[i] >= mid].Update(1, 1, n, i, i, 1);
    110  
    111         for(int i = 1; i <= m; i++)
    112         {
    113             now = oper[i].l;
    114             if(oper[i].x == 0) for(int id = 0; id <= 1; id++) Modify(id, oper[i].l, oper[i].r);
    115             if(oper[i].x == 1) for(int id = 1; id >= 0; id--) Modify(id, oper[i].l, oper[i].r);
    116         }
    117  
    118         res = 0, C[1].Query(1, 1, n, Q, Q);
    119         return res;
    120 }
    121  
    122 int main()
    123 {
    124         n = get();  m = get();
    125         for(int i = 1; i <= n; i++)
    126             a[i] = get();
    127         for(int i = 1; i <= m; i++)
    128             oper[i].x = get(), oper[i].l = get(), oper[i].r = get();
    129  
    130         Q = get();
    131         int l = 1, r = n;
    132         while(l < r - 1)
    133         {
    134             int mid = l + r >> 1;
    135             if(Check(mid)) l = mid;
    136             else r = mid;
    137         }
    138  
    139         if(Check(r)) printf("%d", r);
    140         else printf("%d", l);
    141 }
    142 
    View Code

      

  • 相关阅读:
    Java 深拷贝和浅拷贝 利用序列化实现深拷贝
    算法题005 剑指Offer面试题29 数组中出现次数超过一半的数字
    算法题003 斐波那契(Fibonacci)数列
    Android Sensors (4) 传感器使用最佳实践
    Android WebView使用基础
    Java 多线程(八) 线程状态图
    算法题006 判断两个链表是否相交
    Java 多线程(五) 多线程的同步
    算法题001 剑指Offer 面试题三:二维数组中的查找
    Android绘制基础及手写绘制实例
  • 原文地址:https://www.cnblogs.com/BearChild/p/7768941.html
Copyright © 2011-2022 走看看