• [HEOI2016/TJOI2016]排序


    链接:https://www.luogu.org/problemnew/show/P2824

    题解:

    思路非常奇特的一道题

    第一次做应该很难想出来。。

    考虑一个序列只有0/1

    那么将区间排序就只需将0/1放在最前面/最后面即可,这个显然是可以用线段树来维护的

    那么考虑原题

    我们可以先二分答案,然后将比这个数大的数标记为1,比这个数小的数标记为0

    另外注意线段树建造的时候要将x和lazy值初始化

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 100000
    #define mid (h+t)/2
    struct re
    {
        int x,h,t,lazy;
    }p[maxn*5];
    int n,m,a[maxn],bb[maxn],b[maxn],c[maxn],d[maxn],f[maxn],goal;
    void updata(int x)
    {
        p[x].x=p[x*2].x+p[x*2+1].x;
    }
    void build(int x,int h,int t)
    {
        p[x].h=h; p[x].t=t; p[x].x=0; p[x].lazy=0;
        if (h==t)
        {
            p[x].x=f[h]; return;
        }
        build(x*2,h,mid); build(x*2+1,mid+1,t);
        updata(x);
    }
    void down(int x)
    {
       if (p[x].lazy)
       {
         p[x].x=(p[x].t-p[x].h+1)*(p[x].lazy-1);
         if (p[x].h!=p[x].t)
         {
           p[x*2].lazy=p[x].lazy;
           p[x*2+1].lazy=p[x].lazy;
         }
         p[x].lazy=0;
      }
    }
    void change(int x,int h,int t,int sum)
    {
        down(x);
        if (p[x].h>t||p[x].t<h) return;
        if (h<=p[x].h&&p[x].t<=t)
        {
            p[x].lazy=sum; down(x);
            return;
        }
        change(x*2,h,t,sum); change(x*2+1,h,t,sum);
        updata(x);
    }
    int query(int x,int h,int t)
    {
        down(x);
        if (p[x].h>t||p[x].t<h) return(0);
        if (h<=p[x].h&&p[x].t<=t)
        {
            return(p[x].x);
        }
        return(query(x*2,h,t)+query(x*2+1,h,t));
    }
    bool check(int x)
    {
        for (int i=1;i<=n;i++)
          if (a[i]>=x) f[i]=1; else f[i]=0;
        build(1,1,n);
        for (int i=1;i<=m;i++)
        {
            if (bb[i]==0)
            {
              int x=query(1,c[i],d[i]);
              change(1,d[i]-x+1,d[i],2);
              change(1,c[i],d[i]-x,1);    
            }
            else
            {
              int x=query(1,c[i],d[i]);
              change(1,c[i]+x,d[i],1);
              change(1,c[i],c[i]+x-1,2);    
            }
        }
        if (query(1,goal,goal)) return(true); else return(false);
    }
    int main()
    {
        freopen("noip.in","r",stdin);
        freopen("noip.out","w",stdout);
        cin>>n>>m;
        for (int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        for (int i=1;i<=m;i++)
        {
            cin>>bb[i]>>c[i]>>d[i];
        }
        cin>>goal;
        memcpy(b,a,sizeof(a));
        int h=1,t=n;
        sort(b+1,b+n+1);
        while (h<t)
        {
          int midd=(h+t+1)/2;
          if (check(b[midd])) h=midd; else t=midd-1;    
        }
        cout<<b[h];
    }
  • 相关阅读:
    使用ConcurrentHashMap需要知道的细节
    并查集(Union-Find)
    LeetCode2
    补充之前博客的几种排序--希尔排序、堆排序、归并排序
    左式二叉堆
    优先队列的一种实现--堆ADT
    开放地址法散列表ADT
    分离链表法散列ADT
    AVL树
    二叉查找树ADT--C语言描述
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8394967.html
Copyright © 2020-2023  润新知