zoukankan      html  css  js  c++  java
  • [Tjoi2016&Heoi2016]排序

    题目

    bzoj4552

    题解

    二分q位置上的值mid,然后将所有大于mid的数记为1,小于等于mid的数记为0,用线段树维护区间的和

    对于升序排列,及时将所有为1的数放在右边;降序排列就是将所有为0的数放在右边

    最后判断出p位置为1还是0,若为1,则说明mid小于真实值,l=mid+1;若为0,则mid可能大于真实值(注意是可能),记录ans并r=mid

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath> 
    #define N 1000000
    using namespace std;
     
    int n,m,a[N],q;
    int opt[N],cl[N],cr[N];
     
    struct node{int l,r,sum,d;}T[N];
     
    void pushup(int p){T[p].sum=T[p<<1].sum+T[p<<1|1].sum;}
    void pushdown(int p)
    {
        if(T[p].d==-1) return;
        T[p<<1].sum=(T[p<<1].r-T[p<<1].l+1)*T[p].d;
        T[p<<1|1].sum=(T[p<<1|1].r-T[p<<1|1].l+1)*T[p].d;
        T[p<<1].d=T[p<<1|1].d=T[p].d;
        T[p].d=-1;
    }
     
    void build(int p,int x,int y,int v)
    {
        T[p].l=x;T[p].r=y;T[p].d=-1;
        if(x==y) {T[p].sum=(a[x]>v);return;}
        if(x<y)
        {
            int mid=(x+y)>>1;
            build(p<<1,x,mid,v);
            build(p<<1|1,mid+1,y,v);
            pushup(p);
        }
    }
     
    int query(int p,int x,int y)
    {
        int pl=T[p].l,pr=T[p].r;
        if(pl==x&&pr==y) return T[p].sum;
        pushdown(p);
        int mid=(pl+pr)>>1;
        if(y<=mid) return query(p<<1,x,y);
        else if(x>mid) return query(p<<1|1,x,y);
        else return query(p<<1,x,mid)+query(p<<1|1,mid+1,y);
    }
     
    void set(int p,int x,int y,int v)
    {
        int pl=T[p].l,pr=T[p].r;
        if(pl==x&&pr==y)
        {
            T[p].sum=(T[p].r-T[p].l+1)*v;
            T[p].d=v;
            return;
        } 
        pushdown(p);
        int mid=(pl+pr)>>1;
        if(y<=mid) set(p<<1,x,y,v);
        else if(x>mid) set(p<<1|1,x,y,v);
        else
        {
            set(p<<1,x,mid,v);
            set(p<<1|1,mid+1,y,v);
        }
        pushup(p);//
    }
     
    bool check(int x)
    {
        build(1,1,n,x);//建树
        for(int i=1;i<=m;i++)
        {
            int sum=query(1,cl[i],cr[i]);//先求出区间内大于x的个数 
            if(!opt[i])//升序 
            {
                if(sum) set(1,cr[i]-sum+1,cr[i],1);//将1全部放右边
                if(cr[i]-sum>=cl[i]) set(1,cl[i],cr[i]-sum,0); 
            }
            else//降序 
            {
                if(sum) set(1,cl[i],cl[i]+sum-1,1);//将1全部放左边
                if(cl[i]+sum<=cr[i]) set(1,cl[i]+sum,cr[i],0);           
            }
        }
        return query(1,q,q)==0;
    }
     
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=m;i++) scanf("%d%d%d",&opt[i],&cl[i],&cr[i]);
        scanf("%d",&q);
        int l=1,r=n,mid,ans;
        while(l<r)//二分p位置上的值 
        {
            mid=(l+r)>>1;
            if(check(mid)) ans=mid,r=mid;
            else l=mid+1;
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Best Time to Buy and Sell Stock
    Remove Nth Node From End of List
    Unique Paths
    Swap Nodes in Pairs
    Convert Sorted Array to Binary Search Tree
    Populating Next Right Pointers in Each Node
    Maximum Subarray
    Climbing Stairs
    Unique Binary Search Trees
    Remove Duplicates from Sorted Array
  • 原文地址:https://www.cnblogs.com/XYZinc/p/7631445.html
Copyright © 2011-2022 走看看