• BZOJ 4552: [Tjoi2016&Heoi2016]排序


    4552: [Tjoi2016&Heoi2016]排序

    Time Limit: 60 Sec  Memory Limit: 256 MB
    Submit: 579  Solved: 322
    [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表示局部排序的次数。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^5
     

    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

     

    Source

     
    [Submit][Status][Discuss]

    首先二分答案,然后需要知道进行m次排序后p位置上的数字是否大于mid。

    对于一个mid,我们可以把序列里的数字分为两类,即大于mid的数和小于等于mid的数,分别用1和0表示。

    对这些0和1进行排序时,对于一个区间[l,r]进行升序排序,等价于把所有的0放在前面,所有的1放在后面;降序排序反之。

    用线段树支持区间求和及区间修改即可。

      1 #include <bits/stdc++.h>
      2 
      3 #define fread_siz 1024 
      4 
      5 inline int get_c(void)
      6 {
      7     static char buf[fread_siz];
      8     static char *head = buf + fread_siz;
      9     static char *tail = buf + fread_siz;
     10     
     11     if (head == tail)
     12         fread(head = buf, 1, fread_siz, stdin);
     13         
     14     return *head++;
     15 }
     16 
     17 inline int get_i(void)
     18 {
     19     register int ret = 0;
     20     register int neg = false;
     21     register int bit = get_c();
     22     
     23     for (; bit < 48; bit = get_c())
     24         if (bit == '-')neg ^= true;
     25         
     26     for (; bit > 47; bit = get_c())
     27         ret = ret * 10 + bit - 48;
     28         
     29     return neg ? -ret : ret;
     30 }
     31 
     32 const int maxn = 1e5 + 5;
     33 
     34 int n, m;
     35 int total;
     36 int num[maxn];
     37 int map[maxn];
     38 
     39 struct Query
     40 {
     41     int k, l, r;
     42 }qry[maxn];
     43 
     44 int pos;
     45 
     46 struct Node
     47 {
     48     int sum;
     49     int tag;
     50     int lt, rt;
     51 }tree[maxn << 2];
     52 
     53 #define lson(t) (t << 1)
     54 #define rson(r) (t << 1 | 1)
     55 
     56 void build(int t, int l, int r, int k)
     57 {
     58     tree[t].lt = l;
     59     tree[t].rt = r;
     60     tree[t].tag = -1;
     61     
     62     if (l == r)
     63         tree[t].sum = num[l] > k;
     64     else
     65     {
     66         int mid = (l + r) >> 1;
     67         build(lson(t), l, mid, k);
     68         build(rson(t), mid + 1, r, k);
     69         tree[t].sum = tree[lson(t)].sum + tree[rson(t)].sum;
     70     }
     71 }
     72 
     73 void change(int t, int l, int r, int k)
     74 {
     75     if (l > r)return;
     76 
     77     if (l == tree[t].lt && r == tree[t].rt)
     78         tree[t].sum = (r - l + 1) * k, tree[t].tag = k;
     79     else
     80     {
     81         int mid = (tree[t].lt + tree[t].rt) >> 1;
     82         
     83         if (tree[t].tag != -1)
     84         {
     85             change(lson(t), tree[t].lt, mid, tree[t].tag);
     86             change(rson(t), mid + 1, tree[t].rt, tree[t].tag);
     87             tree[t].tag = -1;
     88         }
     89         
     90         if (r <= mid)
     91             change(lson(t), l, r, k);
     92         else if (l > mid)
     93             change(rson(t), l, r, k);
     94         else
     95             change(lson(t), l, mid, k), change(rson(t), mid + 1, r, k);
     96             
     97         tree[t].sum = tree[lson(t)].sum + tree[rson(t)].sum;
     98     }
     99 }
    100 
    101 int query(int t, int l, int r)
    102 {
    103     if (l == tree[t].lt && r == tree[t].rt)
    104         return tree[t].sum;
    105         
    106     int mid = (tree[t].lt + tree[t].rt) >> 1;
    107     
    108     if (tree[t].tag != -1)
    109     {
    110         change(lson(t), tree[t].lt, mid, tree[t].tag);
    111         change(rson(t), mid + 1, tree[t].rt, tree[t].tag);
    112         tree[t].tag = -1;
    113     }
    114     
    115     if (r <= mid)
    116         return query(lson(t), l, r);
    117     else if (l > mid)
    118         return query(rson(t), l, r);
    119     else
    120         return query(lson(t), l, mid) + query(rson(t), mid + 1, r);
    121 }
    122 
    123 inline bool check(int mid)
    124 {
    125     build(1, 1, n, mid);
    126     
    127     for (int i = 1; i <= m; ++i)
    128     {
    129         int q = query(1, qry[i].l, qry[i].r);
    130         
    131         if (qry[i].k)
    132         {
    133             change(1, qry[i].l, qry[i].l + q - 1, 1);
    134             change(1, qry[i].l + q, qry[i].r, 0);
    135         }
    136         else
    137         {
    138             change(1, qry[i].l, qry[i].r - q, 0);
    139             change(1, qry[i].r - q + 1, qry[i].r, 1);
    140         }
    141     }
    142     
    143     return query(1, pos, pos);
    144 }
    145 
    146 signed main(void)
    147 {
    148     n = get_i();
    149     m = get_i();
    150     
    151     for (int i = 1; i <= n; ++i)
    152         num[i] = get_i();
    153         
    154     for (int i = 1; i <= m; ++i)
    155     {
    156         qry[i].k = get_i();
    157         qry[i].l = get_i();
    158         qry[i].r = get_i();
    159     }
    160     
    161     pos = get_i();
    162     
    163     memcpy(map, num, sizeof(map));
    164     std::sort(map + 1, map + 1 + n);
    165     total = std::unique(map + 1, map + 1 + n) - map;
    166     
    167     int lt = 1, rt = total, mid, ans;
    168     
    169     while (lt <= rt)
    170     {
    171         if (check(mid = (lt + rt) >> 1))
    172             lt = mid + 1;
    173         else
    174             rt = mid - 1, ans = mid;
    175     }
    176     
    177     printf("%d
    ", map[ans]);
    178 }

    @Author: YouSiki

  • 相关阅读:
    .Net语言 APP开发平台——Smobiler学习日志:Poplist控件在APP中的应用场景以及代码
    C++ STL 之 set 和 pair
    C++ STL 之 list
    安卓开发之数据库事务的使用
    安卓开发之sql语句增删改查2(利用谷歌封装好的API进行增删改查)
    安卓开发之SimpleAdapter的使用
    安卓开发之ArrayAdapter使用
    安卓开发之打气筒的使用
    安卓开发之ListView入门
    安卓开发之sql语句增删改查
  • 原文地址:https://www.cnblogs.com/yousiki/p/6221698.html
Copyright © 2020-2023  润新知