zoukankan      html  css  js  c++  java
  • [loj3366]嘉年华奖券

    联系绝对值的几何意义/分类讨论,不难发现若$n$张奖券上的数从小到大依次为$a_{i}$,则收益为$sum_{i=1}^{frac{n}{2}}a_{i+frac{n}{2}}-a_{i}$

    假设确定了这$nk$个数字,设这从小到大依次为$a_{i}$,容易发现答案最大不会超过$sum_{i=1}^{frac{nk}{2}}a_{i+frac{nk}{2}}-a_{i}$;同时,如果存在$x>y$满足$a_{x}$为负号且$a_{y}$为正号,就交换$(a_{x},a_{y})$,最终一定可以取到最大值

    再考虑如何确定这$nk$个数字,先取出每一个组中最小的数,符号都为负,然后贪心$frac{nk}{2}$次选择一组将符号为负且最大(原值)的数替换为未被选择的最大的数,使得收益(即两数之和)最大,并用set维护即可

    还有构造方案的问题,由于前者已经证明了必然存在方案,那么随便构造一轮后,这个子问题类似的依然可以证明存在方案,因此每一轮可以任意构造,先优先考虑全是正号/负号的组,其余组再任意选择即可

     1 #include "tickets.h"
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 #define N 1505
     5 vector<vector<int> >a;
     6 priority_queue<pair<int,int> >q;
     7 int n,m,mn[N],mx[N],p[N];
     8 long long find_maximum(int k,vector<vector<int> >c){
     9     a=c;
    10     n=a.size();
    11     m=a[0].size();
    12     for(int i=0;i<n;i++){
    13         a[i].push_back(0);
    14         for(int j=m;j;j--)a[i][j]=a[i][j-1];
    15         a[i][0]=0;
    16     }
    17     for(int i=0;i<n;i++){
    18         mn[i]=k;
    19         q.push(make_pair(a[i][mn[i]]+a[i][m],i));
    20     }
    21     for(int i=0;i<n*k/2;i++){
    22         int x=q.top().second;
    23         q.pop();
    24         mn[x]--;
    25         mx[x]++;
    26         if (mn[x])q.push(make_pair(a[x][mn[x]]+a[x][m-mx[x]],x));
    27     }
    28     long long ans=0;
    29     for(int i=0;i<n;i++){
    30         for(int j=1;j<=mn[i];j++)ans-=a[i][j];
    31         for(int j=m-mx[i]+1;j<=m;j++)ans+=a[i][j];
    32     }
    33     for(int i=0;i<n;i++){
    34         a[i].pop_back();
    35         for(int j=mn[i];j<m-mx[i];j++)a[i][j]=-1;
    36     }
    37     for(int i=0;i<k;i++){
    38         int x=0,y=0;
    39         memset(p,-1,sizeof(p));
    40         for(int j=0;j<n;j++){
    41             if (!mn[j])p[j]=0;
    42             if (!mx[j])p[j]=1;
    43             if ((mn[j])&&(mx[j]))y++;
    44             else x+=2*p[j]-1;
    45         }
    46         y=(x+y)/2;
    47         for(int j=0;j<n;j++)
    48             if ((mn[j])&&(mx[j])){
    49                 p[j]=(y<=0);
    50                 y--;
    51             }
    52         for(int j=0;j<n;j++)
    53             if (p[j])a[j][--mn[j]]=i;
    54             else a[j][m-mx[j]--]=i;
    55     }
    56     allocate_tickets(a);
    57     return ans; 
    58 }
    View Code
  • 相关阅读:
    TypeScript--变量
    TypeScript--Hello
    前端跨域的方式
    内存泄漏与垃圾回收机制
    前端拷贝
    React生命周期16版本
    Redux三大原则
    IE6常见CSS解析Bug及hack
    Redux的应用
    vue-router-基础
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13806571.html
Copyright © 2011-2022 走看看