4552: [Tjoi2016&Heoi2016]排序

4552: [Tjoi2016&Heoi2016]排序

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

题解:

我们二分这个数mid,判断就是把序列中>=mid的数设为1,<mid的设为

如果是0操作,就把0全部放到区间的最前面,1放到最后面,用线段树实现好了。

1操作的话也差不多。

最后看看第q个是1还是0.

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define p1 (p<<1)
#define p2 (p<<1|1)
const int N=100005;
struct node
{
    int a,b,c;
}p[N];
int n,m,i,ans,k,a[N],b[N],t[N<<2],add[N<<2];
void build(int l,int r,int p)
{
    if(l==r)
    {
        t[p]=add[p]=b[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,p1);
    build(mid+1,r,p2);
    t[p]=t[p1]+t[p2];
}
void update(int l,int r,int x,int y,int z,int p)
{
    if(x>y) return;
    if(add[p]==z) return;
    if(x<=l&&r<=y)
    {
        add[p]=z;
        t[p]=z*(r-l+1);
        return;
    }
    int mid=(l+r)>>1;
    if(add[p]!=-1)
    {
        update(l,mid,l,mid,add[p],p1);
        update(mid+1,r,mid+1,r,add[p],p2);
        add[p]=-1;
    }
    if(x<=mid) update(l,mid,x,y,z,p1);
    if(y>mid) update(mid+1,r,x,y,z,p2);
    t[p]=t[p1]+t[p2];
    //cout<<l<<‘ ‘<<r<<‘ ‘<<t[p]<<endl;
}
int solve(int l,int r,int x,int y,int p)
{
    if(x<=l&&r<=y) return t[p];
    int ans=0,mid=(l+r)>>1;
    if(add[p]!=-1)
    {
        update(l,mid,l,mid,add[p],p1);
        update(mid+1,r,mid+1,r,add[p],p2);
        add[p]=-1;
    }
    if(x<=mid) ans+=solve(l,mid,x,y,p1);
    if(y>mid) ans+=solve(mid+1,r,x,y,p2);
    return ans;
}
bool check(int x)
{
    int i;
    for(i=1;i<=n;i++)
        if(a[i]>=x) b[i]=1;else b[i]=0;
    for(i=1;i<=n<<2;i++)
    {
        t[i]=0;
        add[i]=-1;
    }
    build(1,n,1);
    for(i=1;i<=m;i++)
    {
        int sum=solve(1,n,p[i].a,p[i].b,1);
        if(p[i].c==0)
        {
            sum=p[i].b-p[i].a+1-sum;
            update(1,n,p[i].a,p[i].a+sum-1,0,1);
            update(1,n,p[i].a+sum,p[i].b,1,1);
        } else
        {
            update(1,n,p[i].a,p[i].a+sum-1,1,1);
            update(1,n,p[i].a+sum,p[i].b,0,1);
        }
    }
    if(solve(1,n,k,k,1)==0) return 0;else return 1;
}
int erfen(int l,int r)
{
    if(l>r) return r;
    int mid=(l+r)>>1;
    if(check(mid)==0) return erfen(l,mid-1);else
    return erfen(mid+1,r);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<=m;i++)
        scanf("%d%d%d",&p[i].c,&p[i].a,&p[i].b);
    scanf("%d",&k);
    cout<<erfen(1,n);
    return 0;
}
时间: 2024-10-06 07:15:31

4552: [Tjoi2016&Heoi2016]排序的相关文章

[BZOJ] 4552: [Tjoi2016&amp;Heoi2016]排序 #二分+线段树+算法设计策略

4552: [Tjoi2016&Heoi2016]排序 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1451  Solved: 734[Submit][Status][Discuss] Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排 序分为两种:1:(0,l,r

bzoj 4552 [Tjoi2016&amp;Heoi2016]排序——二分答案

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案,把 >= mid 的设成1.< mid 的设成0,之后排序就变成区间赋值了. #include<cstdio> #include<cstring> #include<algorithm> #define ls Ls[cr] #define rs Rs[cr] using namespace std; const int N=1e5+5,

bzoj 4552: [Tjoi2016&amp;Heoi2016]排序

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^

bzoj4552 [Tjoi2016&amp;Heoi2016]排序

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第二

[bzoj4552][Tjoi2016][Heoi2016]排序

Description 给出一个到的全排列,现在对这个全排列序列进行次局部排序,排序分为种: 表示将区间的数字升序排序; 表示将区间的数字降序排序. 最后询问第位置上的数字. Input 第行为两个整数和.表示序列的长度,表示局部排序的次数. 第行为个整数,表示到的一个全排列. 接下来输入行,每行有个整数 为代表升序排序,为1代表降序排序;表示排序的区间. 最后输入一个整数,表示排序完之后询问的位置. Output 输出数据仅有一行一个整数,表示按照顺序将全部的部分排序结束后第位置上的数字. S

bzoj4552 [Tjoi2016&amp;Heoi2016]排序 (线段树+二分)

题意:一个1~n的排列,m个操作: 0 x y:将ax~ay按升序排列: 1 x y:将ax~ay按降序排列. 询问m次操作后第aq的值. 输入:第一行:两个正整数n,m,表示序列的长度与询问的个数: 第二行:一个1~n的排列: 第3~m+2行:每行一个操作. 第m+3行:一个数q表示询问的位置. 输出:一个数表示aq的值. 样例输入: 6 3 1 6 2 5 3 4 0 1 4 1 3 6 0 2 4 3 样例输出: 5 解析:考虑二分答案,将小于答案的数变为0,将大于等于答案的变为1,这样整

bzoj4552【TJOI2016&amp;HEOI2016】排序

4552: [Tjoi2016&Heoi2016]排序 Time Limit: 60 Sec  Memory Limit: 256 MB Submit: 291  Solved: 171 [Submit][Status][Discuss] Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排 序分为两种:1:(0,l,

Bzoj4556: [Tjoi2016&amp;Heoi2016]字符串 后缀数组

4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 169  Solved: 87[Submit][Status][Discuss] Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱子拿到礼物,升职加薪,出任CE O,嫁给高富帅,走上人生巅峰.

BZOJ 4553 Tjoi2016&amp;Heoi2016 序列

Tjoi2016&Heoi2016序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值 可能会变化,但同一个时刻最多只有一个值发生变化.现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你 ,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可 .注意:每种变化最多只有一个值发生变化.在样例输入1中,所有的变化是: 1 2 3 2 2 3 1 3 3 1 1 31 2 4