zoukankan      html  css  js  c++  java
  • 洛谷P2827 NOIP2016 蚯蚓

    题目描述:

    输入 

    输出 

     

    思路分析——70分写法:

      看到每次取出最大值,第一眼想到的就是优先队列,我们可以每一次取完队首元素后将其分开后两段的长度进行计算,再放入队列之中即可但题目中要求,除被切开的蚯蚓外,其余蚯蚓长度要变长,每次把队中元素取出并加上q再放入队中?不用说我们也知道这是不行的,那我们可以考虑定义一个tap来表示当前队内蚯蚓的长度增加的总的长度,每次从队首取出元素,给它加上tap,使它变为它应该的此时的长度,在计算为两段之后将每一段的长度再减去tap的基础上再减一个q(因为其他数都加上了q,相当于队外的元素减q),tap+=q,之后以此类推;之后按照要求输出对应排名的蚯蚓长度即可。

    附上代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 using namespace std;
     6 const int N=1e7+10;
     7 struct Qiuyin{
     8     long long length;
     9     Qiuyin(int a){
    10         length=a;
    11     }
    12     bool operator < (const Qiuyin& a)const{  //重载运算符,方便用优先队列 
    13         return a.length>length;
    14     }
    15 };
    16 int n,m,q,u,v,t;
    17 priority_queue<Qiuyin>p;
    18 int main(){
    19     scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);
    20     for(int i=1;i<=n;++i){
    21         int x;
    22         scanf("%d",&x);
    23         p.push(Qiuyin(x));
    24     }
    25     double cnt=(double)u/(double)v;
    26     int cnt1=t,cnt2=t;  //cnt1,2分别用于记录当前操作到何值时需要输出 
    27     long long tap=0;
    28     for(int i=1;i<=m;++i){
    29         if(i==cnt1){
    30             printf("%lld ",p.top().length+tap);
    31             cnt1+=t;
    32         }
    33         int t=p.top().length+tap; p.pop(); //复原队首元素 
    34         tap+=q;  //更新tap 
    35         int a=(double)t*cnt;
    36         p.push(Qiuyin(a-tap));p.push(Qiuyin(t-a-tap)); //加入队中时要减tap 
    37     }
    38     printf("
    ");
    39     for(int i=1;i<=m+n;++i){
    40         if(i==cnt2){  //以此输出规定排名长度 
    41             printf("%lld ",p.top().length+tap);
    42             cnt2+=t;
    43         }
    44         p.pop();
    45     }
    46     return 0;
    47 }
    View Code

    思路分析——100分写法:

      这道题之中先后插入队中的元素隐含着单调性,我们设先后取出a,b两个元素,由于大的先取,则必有a>=b,我们设题目中的计算切后长度的分数为p,则之后a分为a*p和a-a*p(即a*(1-p))两部分,b分为b*p和b-b*p(即b*(1-p))两部分,因为a>=b,则必有a*p>=b*p;a*(1-p)>=b*(1-p),我们开三个数组,一个储存原数组,sort一遍使它内部元素单调递减(不严格),另两个分别装x*p和x-x*p,每次从队首取元素时,比较三个数组中首指针指向的元素中最大的一个,将最大的取出(并将其首指针+1),分完之后再分别装入两个数组(放在队尾以保证首元素最大)中,之后按要求输出即可(仿照70分写法)。

     附上代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=1e7+10;
     6 int origin[N],cut1[N],cut2[N];
     7 int n,m,q,u,v,t;
     8 int temp=0;
     9 int front_o=1,front_c1=1,front_c2=1;//front表示不同数组的首指针,便于查询数组中z最大值。 
    10 int top1,top2;//用于向数组中添加元素 
    11 bool cmp(int a,int b){ //降序排列 
    12     return a>b;
    13 }
    14 int seek_max(){  //查询并弹出相应队列一体机 
    15     int Max=-1,t; //t用于记录元素所属数组 
    16     if(Max<origin[front_o]+temp&&front_o<=n){ //千万注意首指针的取值范围 
    17         Max=origin[front_o]+temp;
    18         t=1;
    19     }
    20     if(Max<cut1[front_c1]+temp&&front_c1<=top1){
    21         Max=cut1[front_c1]+temp;
    22         t=2;
    23     }
    24     if(Max<cut2[front_c2]+temp&&front_c2<=top2){
    25         Max=cut2[front_c2]+temp;
    26         t=3;
    27     }
    28     if(t==1) front_o++;  //弹出首元素 
    29     else if(t==2) front_c1++;
    30     else front_c2++;
    31     return Max;
    32 }
    33 int main(){
    34     scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);
    35     double cnt=(double)u/(double)v;
    36     for(int i=1;i<=n;++i){
    37         scanf("%d",&origin[i]);
    38     }
    39     int cnt1=t,cnt2=t;
    40     sort(origin+1,origin+1+n,cmp);
    41     for(int i=1;i<=m;++i){
    42         int Max=seek_max();
    43         if(i==cnt1){
    44             printf("%d ",Max);
    45             cnt1+=t;
    46         }
    47         temp+=q;
    48         int a=(double)Max*cnt,b=Max-a;  //类似70分写法 
    49         cut1[++top1]=a-temp;cut2[++top2]=b-temp;
    50     }
    51     printf("
    ");
    52     for(int i=1;i<=n+m;++i){
    53         int Max=seek_max();  //类似70分写法 
    54         if(i==cnt2){
    55             cnt2+=t;
    56             printf("%d ",Max);
    57         }
    58     }
    59     printf("
    ");
    60     return 0;
    61 } 
    View Code
  • 相关阅读:
    类的加载与ClassLoader的理解
    反射:获取Class 类的实例(四种方法)
    磁盘调度算法
    死锁检测算法
    银行家算法
    最低松弛度调度算法模拟
    多级反馈队列调度算法
    内存中:请求调页存储管理方式的模拟
    内存的动态分区分配方式的模拟
    “短进程优先”调度算法
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/12713301.html
Copyright © 2011-2022 走看看