蓝桥杯 Beaver's Calculator By Assassin 归并排序

1.原题目

    问题描述
  从万能词典来的聪明的海狸已经使我们惊讶了一次。他开发了一种新的计算器,他将此命名为"Beaver's Calculator 1.0"。它非常特别,并且被计划使用在各种各样的科学问题中。
  为了测试它,聪明的海狸邀请了n位科学家,编号从1到n。第i位科学家给这个计算器带来了 ki个计算题。第i个科学家带来的问题编号1到n,并且它们必须按照编号一个一个计算,因为对于每个问题的计算都必须依赖前一个问题的计算结果。
  每个教授的每个问题都用一个数 ai, j  来描述,i(1≤i≤n)是科学家的编号,j(1≤j≤ ki )是问题的编号, ai, j  表示解决这个问题所需资源单位的数量。
  这个计算器非常不凡。它一个接一个的解决问题。在一个问题解决后,并且在下一个问题被计算前,计算器分配或解放资源。
  计算器中最昂贵的操作是解放资源,解放远远慢于分配。所以对计算器而言,每一个接下来的问题所需的资源不少于前一个,是非常重要的。
  给你关于这些科学家所给问题的相关信息。你需要给这些问题安排一个顺序,使得“坏对”尽可能少。
  所谓“坏对”,就是相邻两个问题中,后一个问题需求的资源比前一个问题少。别忘了,对于同一个科学家给出的问题,计算它们的相对顺序必须是固定的。
输入格式
  第一行包含一个整数n,表示科学家的人数。接下来n行每行有5个整数,ki, ai, 1, xi, yi, mi (0 ≤ ai, 1 < mi ≤ 109, 1 ≤ xi, yi ≤ 109) ,分别表示第i个科学家的问题个数,第1个问题所需资源单位数,以及3个用来计算 ai, j 的参量。ai, j = (ai, j - 1 * xi + yi)mod mi。
输出格式
  第一行输出一个整数,表示最优顺序下最少的“坏对”个数。
  如果问题的总个数不超过200000,接下来输出  行,表示解决问题的最优顺序。每一行两个用空格隔开的整数,表示这个问题所需的资源单位数和提供这个问题的科学家的编号。
样例输入
2
2 1 1 1 10
2 3 1 1 10
样例输出
0
1 1
2 1
3 2
4 2
数据规模和约定
  20%的数据 n = 2, 1 ≤ ki ≤ 2000;
  另外30%的数据 n = 2, 1 ≤ ki ≤ 200000;
  剩下50%的数据 1 ≤ n ≤ 5000, 1 ≤ ki ≤ 5000。

2.题目分析

感觉整个人是懵逼的,一开始妄想用优先队列实现写着写着觉得不对劲了,然后发现肯定是超时只是拿到了20分…

然后讲一下这个题目的正解:归并排序加上贪心

我们首先列举一下题目中关键的信息点

1.科学家问题它们必须按照编号一个一个计算,因为对于每个问题的计算都必须依赖前一个问题的计算结果
2.如果问题的总个数不超过200000,接下来输出 sum(k)行

一开始想暴力求一下总数是多少,但是真正的做法如下:首先我们知道对于一个科学家的问题解决的顺序是不能改变的,所以每一个科学家带来的任务的坏点对数是固定的 那么结论应该是什么?结果总数就是 一位科学家任务坏点数的最大值!
我们明确一下,因为同一科学家任务顺序不变,插入或者被插入不改变其坏点对数,那么坏点对数至少是一位科学家任务坏点对数最大值那么大。 坏点对说白了就是A[i]比A[i+1]大,那么我们将科学家任务可以分为K个升序段。那么其他科学家段数比最大那位科学家任务分段数少,那么!其他科学家的任务的升序段一定都可以依次插入!这就很像归并排序的原理了!然后我们记录一下最后顺序输出就行了!

写了一下午加上一晚上,太菜了…下面是我的丑代码:

#include
using namespace std;
struct node{
    int pos,count;          //pos表示当前位置,count表示该科学家有的问题总数 
    long long num[5001];    //求出每位科学家的问题值 
}p[5001];
struct ms{                  //答案 
    long long number,id;
}ans[200001],temp[200001];  //temp数组为了sort中间替换 
int n,k,total=0,start,end;
long long length=0;
void merge(int x,int y){
    int mid=(x+y)>>1,i=x,j=mid+1,kkk=x;
    while(i!=mid+1&&j!=y+1){
        if(ans[i].number<=ans[j].number){
            temp[kkk].id=ans[i].id;                 //一定是ans结果不变,然后赋值到temp值中,再将结果整体赋值 
            temp[kkk++].number=ans[i++].number;
        }
        else {
            temp[kkk].id=ans[j].id;
            temp[kkk++].number=ans[j++].number;
        }
    }
    while(i<=mid){
        temp[kkk].id=ans[i].id;
        temp[kkk++].number=ans[i++].number;
    }
    while(j<=y){
        temp[kkk].id=ans[j].id;
        temp[kkk++].number=ans[j++].number;
    }
    for(i=x;i<=y;i++){          //将结果整体赋值 
        ans[i]=temp[i];
    }
}

void mergesort(int x,int y){
    if(xint mid=(x+y)>>1;
        mergesort(x,mid);
        mergesort(mid+1,y);
        merge(x,y);
    }

}
int main(){
    freopen("input.txt","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        long long t1,t2,t3,t4,times=0;
        scanf("%d%lld%lld%lld%lld",&k,&t1,&t2,&t3,&t4);     //注意第一个是%d啊!输入不正确可不行!(不是%lld) 
        p[i].pos=1;
        p[i].count=k; 
        p[i].num[1]=t1;
        length+=k;                  //统计总长 
        for(int j=2;j<=k;j++){
            p[i].num[j]=(p[i].num[j-1]*t2+t3)%t4;
            if(p[i].num[j]1]){
                times++;
            }
        }
        if(times>total){        //更新一位科学家任务坏点对数 
            total=times;
        }
    }
    cout<if(length<=200000){         //注意这是一个条件! 
        start=end=1;
        while(end<=length){
            for(int i=1;i<=n;i++){          //依次写入升序段 
                int position=p[i].count+1;
                for(int j=p[i].pos;j<=p[i].count;j++){
                    if(j!=p[i].pos&&p[i].num[j]1]){
                        position=j;
                        break;
                    }
                    ans[end].id=i;
                    ans[end++].number=p[i].num[j];
                }
                p[i].pos=position;          //重新设置起点 
            }
            mergesort(start,end-1);
            start=end;                      //更新位置 
        }
        for(int i=1;i<=length;i++){
            printf("%lld %lld\n", ans[i].number, ans[i].id);
        }
    }

    return 0;
}

你可能感兴趣的:(排序)