您的位置:首页 > 编程语言 > Go语言

csuoj 1352: New Sorting Algorithm

2013-12-11 22:38 155 查看
因为每个元素都是移动到比它小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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: