zoukankan      html  css  js  c++  java
  • csuoj 1352: New Sorting Algorithm

     因为每个元素都是移动到比它小1位的元素的后面;

    这样的话以后的一定就可以把他们两个打包;

    所以用这种方法最多扫一遍就可以了;

    但是最小的那个数要不要移动呢?

    如果最小的数后面的数都是升序的,那么一直扫到最小的那个数就行了;

    不然的话要完整的扫一遍;

    这个地方我没想清楚,WA的好惨,最后还是看到斌哥的代码才恍然大悟的;

    #include<cstdio>
    #include<algorithm>
    #define maxn 100005
    using namespace std;
    int n,t,m;
    int num[maxn],f[maxn],r[maxn],cnt[maxn];
     
    bool cmp(const int &x,const int &y)
    {
        return num[x]<num[y];
    }
     
    int find(int x)
    {
        return f[x]==x?x:f[x]=find(f[x]);
    }
     
    void merge(int x,int y)
    {
        int xx=find(x);
        int yy=find(y);
        if(xx!=yy)f[yy]=xx,cnt[xx]+=cnt[yy];
    }
     
    void pre()
    {
        for(int i=1; i<=n; i++)r[i]=i;
        sort(r+1,r+n+1,cmp);
        for(int i=1; i<=n; i++)num[r[i]]=i;
        for(int i=1; i<=n; i++)f[i]=i,cnt[i]=1;
    }
     
    void solve()
    {
        long long ans=0;
        bool flag=1;
        for(int i=r[1]; i<n; i++)
            if(num[i]>num[i+1])
            {
                flag=0;
                break;
            }
        if(flag)m=r[1]-1;
        else m=n;
        for(int i=1; i<=m; i++)
        {
            int v=num[i];
            ans+=cnt[v];
            merge(v-1,v);
        }
        printf("%lld
    ",ans);
    }
     
    int main()
    {
    //    freopen("test0.in","r",stdin);
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(int i=1; i<=n; i++)
                scanf("%d",&num[i]);
            pre();
            solve();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    DS博客作业03--树
    DS博客作业02--栈和队列
    DS博客作业01--线性表
    C语言博客作业05--指针
    C语言博客作业04--数组
    C语言博客作业03--函数
    DS博客作业05--查找
    DS博客作业04--图
    DS博客作业02--栈和队列
    C博客作业05-指针
  • 原文地址:https://www.cnblogs.com/yours1103/p/3470246.html
Copyright © 2011-2022 走看看