zoukankan      html  css  js  c++  java
  • luoguP2824 [HEOI2016/TJOI2016]排序(二分答案做法)

    题意

    这题的思路实在巧妙。

    首先我们肯定无法对区间进行sort,那么考虑如何使得sort简化。

    问:如果给的序列是一个0-1序列,让你区间排序,那么怎么做?

    答:建一颗线段树维护sum,求出当前区间中1的数目(query)cnt,之后(以升序排序为例)[l,cnt]都赋值为1,[cnt+1,r]都赋值为0.(赋值没必要更改叶子节点,打个tag就好了)

    考虑如何求出答案(神奇):

    我们二分答案mid,将序列中小于mid的设为0,大于等于mid的设为1,之后用上述方法完成整个操作,单点查询q位置是否为1.

    为什么是正确的:

    我们发现如果第q位为1,那么答案必定大于等于mid。

    update:2019.6.15

    注:代码中必须这么写

    if(L>r||R<l) return;
    

    原因

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define ls(p) (p<<1)
    #define rs(p) (p<<1|1)
    #define sum(p) (tree[p].sum)
    #define tag(p) (tree[p].tag)
    const int maxn=100010;
    int n,m,q,ans;
    int a[maxn],op[maxn],ql[maxn],qr[maxn];
    struct seg
    {
        int sum,tag;
    }tree[maxn<<2];
    void up(int p)
    {
        sum(p)=sum(ls(p))+sum(rs(p));
    }
    void down(int p,int l,int r)
    {
        if(tag(p)<0) return;
        int mid=(l+r)>>1;
        sum(ls(p))=tag(p)*(mid-l+1);sum(rs(p))=tag(p)*(r-mid);
        tag(ls(p))=tag(rs(p))=tag(p);tag(p)=-1;
    }
    void build(int p,int l,int r,int k)
    {
        tag(p)=-1;
        if(l==r)
        {
            sum(p)=a[l]>=k;return;
        }
        int mid=(l+r)>>1;
        build(ls(p),l,mid,k);build(rs(p),mid+1,r,k);
        up(p);
    }
    void change(int p,int L,int R,int l,int r,int k)
    {
        if(L>r||R<l) return;
        if(L>=l&&R<=r)
        {
            sum(p)=(R-L+1)*k;tag(p)=k;return;
        }
        down(p,L,R);
        int mid=(L+R)>>1;
        change(ls(p),L,mid,l,r,k);change(rs(p),mid+1,R,l,r,k);
        up(p);
    }
    int query(int p,int L,int R,int l,int r)
    {
        if(L>r||R<l) return 0;
        if(L>=l&&R<=r) return sum(p);
        down(p,L,R);
        int mid=(L+R)>>1;
        return query(ls(p),L,mid,l,r)+query(rs(p),mid+1,R,l,r);
    }
    bool check(int mid)
    {
        build(1,1,n,mid);
        for(int i=1;i<=m;i++)
        {
            int cnt=query(1,1,n,ql[i],qr[i]);
            if(!op[i])
            {
                change(1,1,n,qr[i]-cnt+1,qr[i],1);
                change(1,1,n,ql[i],qr[i]-cnt,0);
            }
            else
            {
                change(1,1,n,ql[i],ql[i]+cnt-1,1);
                change(1,1,n,ql[i]+cnt,qr[i],0);
            }
        }
        return query(1,1,n,q,q);
    }
    signed main()
    {
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        for(int i=1;i<=m;i++) scanf("%lld%lld%lld",&op[i],&ql[i],&qr[i]);
        scanf("%lld",&q);
        int l=1,r=n;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(check(mid)) ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%lld",ans);
        return 0;
    } 
    
  • 相关阅读:
    Enforcing the correct protocol for partially SSL secured SharePoint sites
    SQL SERVER – Attach mdf file without ldf file in Database
    How to Get SharePoint Client Context in SharePoint Apps (Provider Hosted / SharePoint Access ) in CSOM (Client Side Object Model)
    git--rebase
    flutter widget
    Flutter--FutureBuilder/StreamBuilder(待补)
    Flutter-notification和notificatioLisener
    flutter context踩坑
    Flutter-gestureDetector的滑动事件小试
    flutter -忽略点击事件
  • 原文地址:https://www.cnblogs.com/nofind/p/12035362.html
Copyright © 2011-2022 走看看