zoukankan      html  css  js  c++  java
  • BZOJ4552: [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
     
    刚开始不是很会做。。想起之前Atcoder有道题:
    二分一个数x,大于x为1,小于等于为0
    这道题就可以这么转化
    因为我们只关心q位置上的数,那就二分x,大于x为1,小于为0
    排序其实就是将一段覆盖为0或1,另一段相反,那就线段树搞定了
    处理完后,如果当前这个位置上为0,就说明x>=答案
    //MT_LI
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    struct trnode{
        int l,r,lc,rc;
        int lazy,sum[2];
    }tr[210000];int trlen;
    void bt(int l,int r)
    {
        int now=++trlen;
        tr[now].l=l;tr[now].r=r;tr[now].lc=tr[now].rc=-1;
        tr[now].sum[0]=tr[now].sum[1]=0;tr[now].lazy=-1;
        if(l<r)
        {
            int mid=(l+r)/2;
            tr[now].lc=trlen+1;bt(l,mid);
            tr[now].rc=trlen+1;bt(mid+1,r);
        }
    }
    void update(int x)
    {
        int lc=tr[x].lc,rc=tr[x].rc;
        
        tr[lc].sum[tr[x].lazy]=tr[lc].r-tr[lc].l+1;
        tr[lc].sum[tr[x].lazy^1]=0;
        tr[rc].sum[tr[x].lazy]=tr[rc].r-tr[rc].l+1;
        tr[rc].sum[tr[x].lazy^1]=0;
        
        tr[lc].lazy=tr[rc].lazy=tr[x].lazy;
        
        tr[x].lazy=-1;
    }
    void gai(int now,int p,int c)
    {
        if(tr[now].l==tr[now].r){
            tr[now].sum[c]=1;
            tr[now].sum[c^1]=0;
            return ;
        }
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy!=-1)update(now);
        if(p<=mid)gai(lc,p,c);
        else gai(rc,p,c);
        
        for(int i=0;i<=1;i++)
            tr[now].sum[i]=tr[lc].sum[i]+tr[rc].sum[i];
    }
    void change(int now,int l,int r,int c)
    {
        if(l==tr[now].l&&r==tr[now].r)
        {
            tr[now].sum[c]=r-l+1;
            tr[now].sum[c^1]=0;tr[now].lazy=c;
            return ;
        }
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy!=-1)update(now);
        if(mid+1<=l)change(rc,l,r,c);
        else if(r<=mid)change(lc,l,r,c);
        else change(lc,l,mid,c),change(rc,mid+1,r,c);
        for(int i=0;i<=1;i++)
            tr[now].sum[i]=tr[lc].sum[i]+tr[rc].sum[i];
    }
    int find(int now,int p)
    {
        if(tr[now].l==tr[now].r){return tr[now].sum[1]>tr[now].sum[0]?1:0;}
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy!=-1)update(now);
        if(p<=mid)return find(lc,p);
        else return find(rc,p);
    }
    int findsum(int now,int l,int r,int c)
    {
        if(l==tr[now].l&&r==tr[now].r)return tr[now].sum[c];
        int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy!=-1)update(now);
        if(mid+1<=l)return findsum(rc,l,r,c);
        else if(r<=mid)return findsum(lc,l,r,c);
        else return findsum(lc,l,mid,c)+findsum(rc,mid+1,r,c);
    }
    int n,m,q;
    int a[110000];
    struct node{
        int op,l,r;
    }Q[110000];
    bool check(int mid)
    {
        for(int i=1;i<=n;i++)
        {
            if(a[i]<=mid)gai(1,i,0);
            else gai(1,i,1);
        }
        for(int i=1;i<=m;i++)
        {
            int z=findsum(1,Q[i].l,Q[i].r,0),o=findsum(1,Q[i].l,Q[i].r,1);
            if(Q[i].op==0)
            {
                if(z>0)change(1,Q[i].l,Q[i].l+z-1,0);
                if(o>0)change(1,Q[i].l+z,Q[i].r,1);
            }
            else
            {
                if(o>0)change(1,Q[i].l,Q[i].l+o-1,1);
                if(z>0)change(1,Q[i].l+o,Q[i].r,0);
            }
        }
        return find(1,q);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        trlen=0;bt(1,n);
        for(int i=1;i<=m;i++)scanf("%d%d%d",&Q[i].op,&Q[i].l,&Q[i].r);
        scanf("%d",&q);
        int ans,l=1,r=n;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(check(mid))l=mid+1;
            else r=mid-1,ans=mid;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Balsamiq Mockups完全手册
    LPTSTR、 LPCSTR、LPCTSTR、LPSTR的来源及意义(转)
    Socket编程
    在窗口中绘图(转)
    写博客
    _beginthread还是CreateThread (转)
    CString 与其他类型的转换
    TCP/IP 详述 (转大部分)
    解决svgview控件ax_XXX_Control.SetSRC中出现内存不能为write 遥远的青苹果
    new 与malloc问题 遥远的青苹果
  • 原文地址:https://www.cnblogs.com/MT-LI/p/9762593.html
Copyright © 2011-2022 走看看