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\n",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

 

posted @ 2013-12-11 22:38  Yours1103  阅读(153)  评论(0编辑  收藏  举报