zoukankan      html  css  js  c++  java
  • NOI.AC 32 Sort——分治

    题目:http://noi.ac/problem/32

    从全是0和1的情况入手,可以像线段树一样分治下去,回到本层的时候就是左半部的右边是1,右半部的左边是0,把这两部分换一下就行。代价和时间一样是nlogn。

    不全是0和1,可以像快速排序一样,先找一个基准,然后小于它的是0、大于它的是1,调用上一行的那个函数;本层弄好0和1以后,递归到全是0的部分和全是1的部分即可。这样代价和时间都是nlog^2n。

    那个基准找得不好的话,一不小心就陷入死循环。所以自己还专门unique了一下,确保不会递归到自己。不过还是很心虚。

    看别人有很好的写法,就是以基准(它的值也是中间位置的值,但不用unique)为mid,调用另一个和递归自己的范围就都可以是 l,mid-1 和 mid+1,r 了,这样就不会死循环。而且那个人没有返回那个0和1的边界,而是每次现从mid开始找;只是觉得这样写法扩展自己思路。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=5e4+5;
    int n,a[N],tmp[N],top;
    bool b[N];
    int rdn()
    {
        int ret=0;bool fx=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
        while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
        return fx?ret:-ret;
    }
    int deb;
    int calc(int l,int r)
    {
    //    if(deb<=30)printf("calc l=%d r=%d bl=%d
    ",l,r,b[l]),deb++;
        int p=r+1;
        for(int i=l;i<=r;i++) if(b[i]){p=i;break;}
        if(p>r) return p-1;//all 0
        p=l-1;
        for(int i=l;i<=r;i++) if(!b[i]){p=i;break;}
        if(p<l)return p;//all 1
    
        int mid=l+r>>1;
        int p0=calc(l,mid),p1=calc(mid+1,r);
    //    if(deb<=30)printf("calc:l=%d r=%d p0=%d p1=%d ",l,r,p0,p1);
        if(p0+1<p1)
        {
            printf("%d %d
    ",p0+1,p1);
            for(int i=p0+1,j=p1;i<j;i++,j--)
                swap(a[i],a[j]),swap(b[i],b[j]);
        }
    
        p=r+1;
        for(int i=l+1;i<=r;i++) if(b[i]){p=i-1;break;}
    //    if(deb<=30)printf("p=%d
    ",p);
        return p;
    }
    void solve(int l,int r)
    {
        if(l>=r)return;
        bool flag=0;
        for(int i=l+1;i<=r;i++) if(a[i]!=a[i-1]){flag=1;break;}
        if(!flag)return;
        
        top=0;
        for(int i=l;i<=r;i++) tmp[++top]=a[i];
        sort(tmp+1,tmp+top+1);
        top=unique(tmp+1,tmp+top+1)-tmp-1;//
        int base=tmp[top>>1];
    //    if(deb<=30)printf("base=%d
    ",base);
        
        for(int i=l;i<=r;i++)
            b[i]=(a[i]>base);//配合下取整的top
    /*    if(deb<=30)
        {
            printf("psol ");
            for(int i=l;i<=r;i++)printf("%d ",b[i]);
            printf("
    
    ");
        }
    */
    
    //    if(deb<=30)printf("solve l=%d r=%d
    ",l,r);
        int d=calc(l,r);
    //    if(deb<=30)printf("d=%d
    ",d);
    /*
        if(deb<=30)
        {
            printf("csol ");
            for(int i=l;i<=r;i++)printf("%d ",b[i]);
            printf("
    
    ");
        }
    */
        solve(l,d); solve(d+1,r);
    }
    int main()
    {
        n=rdn();
        for(int i=1;i<=n;i++) a[i]=rdn();
        solve(1,n);
        printf("-1 -1
    ");
        return 0;
    }
  • 相关阅读:
    List分组和排序
    IOS 可靠性测试 iosMonkey
    Mac 10.10 下安装jdk 1.7 以上
    Ubuntu 无法拖拽复制
    Ubuntu 环境安装整理
    vmware 中 ubuntu linux 安装vmware tools
    Vmware linux 安装 Vmware Tools 提示只读
    Ubuntu_文件夹名字转化成英文
    Ubuntu_开启root 登陆
    Tomcat 用户配置
  • 原文地址:https://www.cnblogs.com/Narh/p/9711132.html
Copyright © 2011-2022 走看看