BZOJ 4552: [Tjoi2016&Heoi2016]排序

来源:互联网 发布:小米windows平板3 编辑:程序博客网 时间:2024/05/24 15:38

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

分析

我们二分一个x,对于每一个比x小的数,我们就把他变为0,反之就把他变为1。
对于每一个排序操作,升序就是把0扔到前面,把1扔到后面,最后的结果就是答案,至于0和1拿线段树维护一下就好

代码

#include <bits/stdc++.h>#define N 100100struct NOTE{    int sum,cover;    bool f;}t[N * 5];int Q[N][3];int num[N];int n,m,p;void change(int p,int l,int r,int v){    t[p].sum = (v?0:r - l + 1);    t[p].cover = v;    t[p].f = true;}void down(int p,int l,int r){    int mid = (l + r) >> 1;    if (t[p].f)    {        change(p * 2,l,mid,t[p].cover);        change(p * 2 + 1,mid + 1,r,t[p].cover);        t[p].f = false;    }}void insert(int p,int l,int r,int x,int y,int v){    if (x > y)        return;    if (l == x && r == y)    {        change(p,l,r,v);        return;    }    down(p,l,r);    int mid = (l + r) >> 1;    if (y <= mid)        insert(p * 2,l,mid,x,y,v);        else        if (x > mid)            insert(p * 2 + 1,mid + 1,r,x,y,v);            else            {                insert(p * 2,l,mid,x,mid,v);                insert(p * 2 + 1,mid + 1,r,mid + 1,y,v);            }    t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;}int getSum(int p,int l,int r,int x,int y){    if (l == x && r == y)        return t[p].sum;    down(p,l,r);    int mid = (l + r) >> 1;    if (y <= mid)        return getSum(p * 2,l,mid,x,y);        else        if (x > mid)            return getSum(p * 2 + 1,mid + 1,r,x,y);            else return getSum(p * 2,l,mid,x,mid) + getSum(p * 2 + 1,mid + 1,r,mid + 1,y);}bool check(int x){    for (int i = 1; i <= n; i++)        if (num[i] < x)            insert(1,1,n,i,i,0);            else insert(1,1,n,i,i,1);    for (int i = 1; i <= m; i++)    {        int tot = getSum(1,1,n,Q[i][1],Q[i][2]);        if (Q[i][0])        {            insert(1,1,n,Q[i][1],Q[i][2] - tot,1);            insert(1,1,n,Q[i][2] - tot + 1,Q[i][2],0);        }        else        {            insert(1,1,n,Q[i][1],Q[i][1] + tot - 1,0);            insert(1,1,n,Q[i][1] + tot,Q[i][2],1);        }    }    return !getSum(1,1,n,p,p);}int main(){    scanf("%d%d",&n,&m);    for (int i = 1; i <= n; i++)        scanf("%d",&num[i]);    for (int i = 1; i <= m; i++)        scanf("%d%d%d",&Q[i][0],&Q[i][1],&Q[i][2]);    scanf("%d",&p);    int l = 1, r = n;    while (l < r)    {        int mid = (l + r + 1) >> 1;        if (check(mid))            l = mid;            else r = mid - 1;    }    printf("%d\n",l);}
0 0
原创粉丝点击