zoj 长沙 Bizarre Routine 模拟

简介:

     题目给了个快排程序,要求构造序列使比较次数等于except。

     于是给定n,我们可以求出可以到达的最小比较次数,和最大比较次数,n*(n-1)/2

     根据快排,每次划分,左边是比其小的数,右边是大的。因此如果划分序列,只需让ans[m]=m;即可划分为m-l-1和r-mid两个,比赛的时候就这里没想清楚。

     而最小值和(Min[x]+Min[len-x])最大值和都是单调递减的,二分即可

    最后再交换两次,回到k位置即可

    其实整个过程就是模拟下快排的逆过程

/*
author:jxy
lang:C/C++
university:China,Xidian University
**If you need to reprint,please indicate the source**
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int Low[10005];
int A,B;
int ans[10005];
int Mi(int n)//确定下界
{
    if(n<=1)return 0;
    if(~Low[n])return Low[n];
    return Low[n]=Mi(n/2)+Mi(n-1-n/2)+n-1;
}
void solve(int l,int r,int e)
{
    if(l>r)return;
    if(l==r)
    {
        ans[l]=l;
        return;
    }
    int len=r-l;
    int ll=0,rr=(len+1)>>1,mid;
    e-=len;
    while(ll<rr)//二分查找划分长度
    {
        mid=(ll+rr)>>1;
        if(Mi(mid)+Mi(len-mid)>e)ll=mid+1;
        else rr=mid;
    }
    mid=ll+l;
    solve(l,mid-1,Mi(ll));
    solve(mid+1,r,e-Mi(ll));
    ans[mid]=mid;
    swap(ans[mid],ans[r]);
    swap(ans[r],ans[(A*l+B*r)/(A+B)]);//返回标兵
}
int main()
{
    int n,e;
    memset(Low,-1,sizeof(Low));
    while(~scanf("%d%d%d%d",&n,&e,&A,&B))
    {
        if(Mi(n)>e||n*(n-1)/2<e) puts("NOWAY");
        else
        {
            solve(1,n,e);
            for(int i=1;i<=n;i++)
            {
                if(i>1)putchar(' ');
                printf("%d",ans[i]);
            }
            puts("");
        }
    }
}


这边是测试程序

#include <cstdio>
#include<iostream>
#include <algorithm>
using namespace std;
int T,A,B;
bool less_than(int x, int y) {
	T++;
	return x < y;
}
void work(int array[], int l, int r) {
	if (l >= r) return;
	swap(array[(l * A + r * B) / (A + B)], array[r]);
	int index = l;
	for (int i = l; i < r; i++)
		if (less_than(array[i], array[r]))
			swap(array[index++], array[i]);
	swap(array[r], array[index]);
	work(array, l, index - 1);
	work(array, index + 1, r);
}
int array[100000];

int main() {
    int n,expect;
	while(~scanf("%d%d%d%d",&n,&expect,&A,&B))
    {
        T=0;
        for(int i=0;i<n;i++)
            scanf("%d",&array[i]);
        work(array, 0, n - 1);
        if (T == expect)
            puts("YES");
        else
            puts("NO");
    }
}




目录
相关文章
|
9月前
|
C语言
CPP2022-21-期中测试(上)
CPP2022-21-期中测试
79 0
|
5月前
|
存储 小程序 数据库
给ta打造一款专属的情侣小程序
给ta打造一款专属的情侣小程序
36 0
PTA 7-2 找奇葩 (20 分)
在一个长度为 n 的正整数序列中,所有的奇数都出现了偶数次,只有一个奇葩奇数出现了奇数次。你的任务就是找出这个奇葩。
77 0
|
9月前
|
机器学习/深度学习
CPP2022-21-期中测试(下)
CPP2022-21-期中测试(下)
187 0
|
12月前
(数学)(必要解题步骤)2021icpc上海D. Strange Fractions
(数学)(必要解题步骤)2021icpc上海D. Strange Fractions
43 0
【CCCC】L2-029 特立独行的幸福 (25分),模拟题,set用法
【CCCC】L2-029 特立独行的幸福 (25分),模拟题,set用法
128 0
2020ICPC昆明站——J.Mr. Main and Windmills(计算几何)
2020ICPC昆明站——J.Mr. Main and Windmills(计算几何)
97 0
2020ICPC昆明站——J.Mr. Main and Windmills(计算几何)