ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[loj3776]Uplifting Excursion

2022-06-07 21:03:32  阅读:101  来源: 互联网

标签:le Uplifting ll int sum loj3776 now Excursion define


不妨假设$L\le \sum_{|i|\le n}i\cdot a_{i}$,否则可以交换$a_{i}$和$a_{-i}$并将$L$取相反数

贪心:$\forall i\le 0$取$a_{i}$个$i$,$\forall i>0$依次取$\lfloor\frac{L-L_{now}}{i}\rfloor$个$i$(其中$L_{now}$为当前元素和)

注意到最终$L_{now}\in (L-m,L]$(若$L<L_{now}$显然无解),并考虑调整:

任取最优解,每次加入/删除一个元素,根据贪心$加入的最小元素>0,删除的最大元素$

每次调整至多使得$L_{now}\pm m$,最终$L_{now}=L$,则存在一种方式使得$|L-L_{now}|\le m$

若某个$L_{now}$重复出现,记其间加入和删除的数分别为$A$和$B$,则$\sum_{x\in A}x=\sum_{x\in B}x$

结合前者的性质,不难证明$|A|<|B|$,进而这一段调整使得元素个数减少,无意义

换言之,每一个$L_{now}$至多出现$1$次,共计至多调整$o(m)$次,进而背包值域为$o(m^{2})$

使用单调队列优化,总复杂度为$o(m^{3})$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1000
 4 #define M 400000
 5 #define ll long long
 6 int n,S,q[M];ll m,sum,ans,a[N],b[N],g[M],f[M];
 7 void turn(int i,int p,ll cnt){
 8     if (i>0){
 9         for(int j=0;j<i;j++){
10             int l=1,r=0;
11             for(int k=j;k<=(S<<1);k+=i){
12                 if (f[k]>=0){
13                     g[k]=f[k]-p*(k/i);
14                     while ((l<=r)&&(g[q[r]]<g[k]))r--;
15                     q[++r]=k;
16                 }
17                 while ((l<=r)&&(q[l]<k-cnt*i))l++;
18                 f[k]=(l<=r ? g[q[l]]+p*(k/i) : -1);
19             }
20         }
21     }
22     else{
23         for(int j=0;j<-i;j++){
24             int l=1,r=0;
25             for(int k=(S<<1)-j;k>=0;k+=i){
26                 if (f[k]>=0){
27                     g[k]=f[k]-p*(k/i);
28                     while ((l<=r)&&(g[q[r]]<g[k]))r--;
29                     q[++r]=k;
30                 }
31                 while ((l<=r)&&(q[l]>k-cnt*i))l++;
32                 f[k]=(l<=r ? g[q[l]]+p*(k/i) : -1);
33             }
34         }
35     }
36 }
37 int main(){
38     scanf("%d%lld",&n,&m);
39     for(int i=-n;i<=n;i++){
40         scanf("%lld",&a[i+n]);
41         sum+=i*a[i+n];
42     }
43     if (m>sum)m=-m,reverse(a,a+(n<<1)+1);
44     S=2*n*n,sum=0;
45     for(int i=-n;i<=0;i++){
46         b[i+n]=a[i+n];
47         sum+=i*b[i+n],ans+=b[i+n];
48     }
49     if (m<sum){
50         printf("impossible\n");
51         return 0;
52     }
53     for(int i=1;i<=n;i++){
54         b[i+n]=min((m-sum)/i,a[i+n]);
55         sum+=i*b[i+n],ans+=b[i+n];
56     }
57     memset(f,-1,sizeof(f));
58     f[S]=ans;
59     for(int i=-n;i<=n;i++)turn(-i,-1,b[i+n]),turn(i,1,a[i+n]-b[i+n]);
60     if (f[S+(m-sum)]<0)printf("impossible\n");
61     else printf("%lld\n",f[S+(m-sum)]);
62     return 0;
63 }
View Code

 

标签:le,Uplifting,ll,int,sum,loj3776,now,Excursion,define
来源: https://www.cnblogs.com/PYWBKTDA/p/16353369.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有