[HEOI2016/TJOI2016]排序

Posted zutter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HEOI2016/TJOI2016]排序相关的知识,希望对你有一定的参考价值。

4552: [Tjoi2016&Heoi2016]排序

Time Limit: 60 Sec Memory Limit: 256 MB
Submit: 2366 Solved: 1188
[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

Source

[Submit][Status][Discuss]


二分+线段树
两个log ==
然后就随便做啦


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define update(now) d[now]=d[now*2]+d[now*2+1]
#define LL long long
#define M 400001
#define max(a,b) ((a)>(b)? (a):(b))
#define min(a,b) ((a)<(b)? (a):(b))

using namespace std;

int i,m,n,h,j,k,d[M],a[M], s[M][3],q,maxx,b[M],lazy[M];

void down(int now,int l,int r)
{
    if(!b[now]) return ;
    int mid=(l+r)>>1;
    d[now*2]=lazy[now]*(mid-l+1);
    d[now*2+1]=lazy[now]*(r-mid);
    lazy[now*2]=lazy[now*2+1]=lazy[now];
    b[now*2]=b[now*2+1]=1;
    b[now]=lazy[now]=0;
}

void built(int now,int l,int r,int z)
{
    if(l==r) 
    {
        if(a[l]>=z) d[now]=1;
        else d[now]=0;
        lazy[now]=b[now]=0;
        return;
    }
    int mid=(l+r)>>1;
    built(now*2,l,mid,z);
    built(now*2+1,mid+1,r,z);
    update(now);
}

void modify(int now,int l,int r,int ll,int rr,int z)
{
    if(l>=ll && r<=rr) 
    {
        d[now]=(r-l+1)*z;
        lazy[now]=z;
        b[now]=1;
        return ;
    }
    down(now,l,r);
    int mid=(l+r)>>1;
    if(ll<=mid) modify(now*2,l,mid,ll,rr,z);
    if(rr>mid) modify(now*2+1,mid+1,r,ll,rr,z);
    update(now);
}

int find1(int now,int l,int r,int ll,int rr)
{
    if(l>=ll && r<=rr) return d[now];
    int mid=(l+r)>>1,ans=0;
    down(now,l,r);
    if(ll<=mid) ans+=find1(now*2,l,mid,ll,rr);
    if(rr>mid) ans+=find1(now*2+1,mid+1,r,ll,rr);
    return ans;
}

int find(int now,int l,int r,int w)
{
    if(l==r) return d[now];
    int mid=(l+r)>>1;
    down(now,l,r);
    if(w<=mid) return find(now*2,l,mid,w);
    return find(now*2+1,mid+1,r,w);
}

bool check(int now)
{
    for(int i=1;i<=m;i++)
    {
        int t=find1(1,1,n,s[i][1],s[i][2]);
        if(!t) continue;
        if(s[i][0])
        {
            modify(1,1,n,s[i][1]+t,s[i][2],0);
            modify(1,1,n,s[i][1],s[i][1]+t-1,1);
        }
        else 
        {
            modify(1,1,n,s[i][2]-t+1,s[i][2],1);
            modify(1,1,n,s[i][1],s[i][2]-t,0);
        }
    }
    return find(1,1,n,q); 
}

int ef(int l,int r)
{
    int mid=l,tmp=l;
    while(r>=l)
    {
        mid=(l+r)>>1;
        memset(b,0,sizeof(b));
        memset(d,0,sizeof(d));
        memset(lazy,0,sizeof(lazy));
        built(1,1,n,mid);
        if(check(mid)) tmp=mid, l=mid+1;
        else r=mid-1;
    }
    return tmp;
}

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",&s[i][0],&s[i][1],&s[i][2]);
    scanf("%d",&q);
    printf("%d",ef(0,n));
}









以上是关于[HEOI2016/TJOI2016]排序的主要内容,如果未能解决你的问题,请参考以下文章

[HEOI2016/TJOI2016]排序 解题报告

「Luogu2824」[HEOI2016/TJOI2016]排序

[HEOI2016/TJOI2016]排序

[HEOI2016/TJOI2016]排序

HEOI2016/TJOI2016 排序

[HEOI2016/TJOI2016]排序