uoj386 【UNR #3】鸽子固定器

link

(似乎很久没写题解了)

 

题意:

n个物品,每个物品有a,b两个值,给定A,B,现在最多选其中m个,要求最大化选出的物品中【b权值和的B次方-a极差的A次方】。

$n\leq 2\times 10^5,m\leq 50.$

 

花絮:

大概全场最早ac的两人是miaom&wzf2000,用了非标算的“神奇的做法”,太强辣。

 

题解:

按照a排序以后转化为选定一个区间以后最大化区间内部的b权值和。

然后考虑两种情况:

  • 如果区间长度小于等于m,那么一定是选择连续一段。
  • 否则,区间内部剩余没有选择的物品,它们的b权值一定比选择的都小,否则可以替换获得更优解。

第一种情况暴力,第二种用链表维护,从小到大删去数,那么每次选择的同样是连续一段。

时间复杂度$\mathcal{O}(nm)$。

 

code:

 1 #include<bits/stdc++.h>
 2 #define rep(i,x,y) for (int i=(x);i<=(y);i++)
 3 #define ll long long
 4 #define inf 1000000001
 5 #define y1 y1___
 6 using namespace std;
 7 ll read(){
 8     char ch=getchar();ll x=0;int op=1;
 9     for (;!isdigit(ch);ch=getchar()) if (ch=='-') op=-1;
10     for (;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
11     return x*op;
12 }
13 #define N 300005
14 int n,m,A,B,id[N],l[N],r[N];ll ans,a1[N],a2[N],b1[N],b2[N];
15 struct node{
16     int a,b;
17     node(){}
18     node(int a_,int b_){a=a_,b=b_;}
19 }q[N];
20 bool cmp(node x,node y){return x.a<y.a;}
21 bool cmp2(int x,int y){return q[x].b<q[y].b||q[x].b==q[y].b&&x<y;}
22 void upd(ll x,ll y){
23     if (B==2) x=x*x;if (A==2) y=y*y;
24     ans=max(ans,x-y);
25 }
26 int main(){
27     // freopen("A.in","r",stdin);
28     // freopen("A.out","w",stdout);
29     n=read(),m=read(),A=read(),B=read();
30     rep (i,1,n) q[i].a=read(),q[i].b=read(),id[i]=i,l[i]=i-1,r[i]=i+1;
31     q[0]=node(0,0);q[n+1]=node(inf,0);
32     r[0]=1,l[n+1]=n,l[0]=0,r[n+1]=n+1;
33     sort(&q[1],&q[n+1],cmp);
34     sort(&id[1],&id[n+1],cmp2);
35     rep (i,1,n){//区间长度小于等于m
36         ll sum=0;
37         for (int j=i;j<=n&&j<=i+m-1;j++){
38             sum+=q[j].b;
39             upd(sum,q[j].a-q[i].a);
40         }
41     }
42     rep (i,1,n){//区间长度大于m,从小到大删数
43         int x=id[i];
44         b1[0]=q[x].b,b2[0]=0;a1[0]=a2[0]=q[x].a;
45         for (int j=1,l_=l[x],r_=r[x];j<=m;j++){
46             b1[j]=b1[j-1]+q[l_].b,b2[j]=b2[j-1]+q[r_].b;
47             a1[j]=q[l_].a,a2[j]=q[r_].a;
48             l_=l[l_],r_=r[r_];
49         }
50         rep (j,0,m-1) upd(b1[j]+b2[m-j-1],a2[m-j-1]-a1[j]);
51         r[l[x]]=r[x],l[r[x]]=l[x];
52     }
53     cout<<ans<<'\n';
54     return 0;
55 }
View Code

 

posted @ 2018-07-14 15:26  bestfy  阅读(428)  评论(0编辑  收藏  举报