关键词:
先说说二分的思路:
对数列中每个数字都减去当前二分的答案,然后求出前缀和,如果前缀和在某个位置加上前M个的最小值大于0,那么就可以更新答案
事实上,减去了当前二分的答案之后,就相当于在与这一段区间都为二分答案的序列互相比较了,剩下只需要维护前M个最小值即可
注意输出答案不要四舍五入,并且要乘以1000,那么就给所有数字乘上10000,最后除以10即可
代码:
#include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf("%lld %lld",&a,&b) #define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c) #define scs(a) scanf("%s",a) #define schar(a) scanf("%c",&a) #define pr(a) printf("%lld",a) #define fo(i,a,b) for(int i=a;i<b;++i) #define re(i,a,b) for(int i=a;i<=b;++i) #define rfo(i,a,b) for(int i=a;i>b;--i) #define rre(i,a,b) for(int i=a;i>=b;--i) #define prn() printf(" ") #define prs() printf(" ") #define mkp make_pair #define pii pair<int,int> #define pub(a) push_back(a) #define pob() pop_back() #define puf(a) push_front(a) #define pof() pop_front() #define fst first #define snd second #define frt front() #define bak back() #define mem0(a) memset(a,0,sizeof(a)) #define memmx(a) memset(a,0x3f3f,sizeof(a)) #define memmn(a) memset(a,-0x3f3f,sizeof(a)) #define debug #define db double #define yyes cout<<"YES"<<endl; #define nno cout<<"NO"<<endl; #define all(i,a) for(auto i=a.begin();i!=a.end();++i) using namespace std; typedef vector<int> vei; typedef vector<pii> vep; typedef map<int,int> mpii; typedef map<char,int> mpci; typedef map<string,int> mpsi; typedef deque<int> deqi; typedef deque<char> deqc; typedef priority_queue<int> mxpq; typedef priority_queue<int,vector<int>,greater<int> > mnpq; typedef priority_queue<pii> mxpqii; typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii; const int maxn=500005; const int inf=0x3f3f3f3f3f3f3f3f; const int MOD=100000007; const db eps=1e-10; const db pi=3.1415926535; int qpow(int a,int b)int tmp=a%MOD,ans=1;while(b)if(b&1)ans*=tmp,ans%=MOD;tmp*=tmp,tmp%=MOD,b>>=1;return ans; int lowbit(int x)return x&-x; int max(int a,int b)return a>b?a:b; int min(int a,int b)return a<b?a:b; int mmax(int a,int b,int c)return max(a,max(b,c)); int mmin(int a,int b,int c)return min(a,min(b,c)); void mod(int &a)a+=MOD;a%=MOD; bool chk(int now); int half(int l,int r)while(l<=r)int m=(l+r)/2;if(chk(m))l=m+1;else r=m-1;return l; int ll(int p)return p<<1; int rr(int p)return p<<1|1; int mm(int l,int r)return (l+r)/2; int lg(int x)if(x==0) return 1;return (int)log2(x)+1; bool smleql(db a,db b)if(a<b||fabs(a-b)<=eps)return true;return false; bool bigeql(db a,db b)if(a>b||fabs(a-b)<=eps)return true;return false; bool eql(db a,db b)if(fabs(a-b)<eps) return 1;return 0; db len(db a,db b,db c,db d)return sqrt((a-c)*(a-c)+(b-d)*(b-d)); bool isp(int x)if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true; inline int read() char ch=getchar();int s=0,w=1; while(ch<48||ch>57)if(ch==‘-‘)w=-1;ch=getchar(); while(ch>=48&&ch<=57)s=(s<<1)+(s<<3)+ch-48;ch=getchar(); return s*w; inline void write(int x) if(x<0)putchar(‘-‘),x=-x; if(x>9)write(x/10); putchar(x%10+48); int gcd(int a, int b) if(a==0) return b; if(b==0) return a; if(!(a&1)&&!(b&1)) return gcd(a>>1,b>>1)<<1; else if(!(b&1)) return gcd(a,b>>1); else if(!(a&1)) return gcd(a>>1,b); else return gcd(abs(a-b),min(a,b)); int lcm(int x,int y)return x*y/gcd(x,y); int n,m,a[maxn],s[maxn]; bool chk(int now) int mn=inf; re(i,1,n) s[i]=s[i-1]+a[i]-now; if(i>=m) mn=min(mn,s[i-m]); if(s[i]>mn) return 1; return 0; signed main() ios_base::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>n>>m; re(i,1,n) cin>>a[i],a[i]*=10000; cout<<half(1,1e9)/10; return 0;
事实上本题还可以利用斜率,考虑到平均数可以写成:(s[j]-s[i-1])/(j-(i-1))的形式,其中s是前缀和
不难发现这就是两个坐标点的二维坐标,意味着我们现在要求出j-i+1>=m的最大斜率
考虑到这题不存在斜率无穷大的情况,实际处理起来还要方便许多
注意到两个步骤:删除上凸线、维护最大斜率,分别对应了出队尾和出队首
显然发现相对于XY段,YZ一定不能起到更新答案的作用,那么就弹出YZ段。
此外每次还要不断弹出队首,直到找到最大斜率点为止。
代码:
#include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf("%lld %lld",&a,&b) #define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c) #define scs(a) scanf("%s",a) #define schar(a) scanf("%c",&a) #define pr(a) printf("%lld",a) #define fo(i,a,b) for(int i=a;i<b;++i) #define re(i,a,b) for(int i=a;i<=b;++i) #define rfo(i,a,b) for(int i=a;i>b;--i) #define rre(i,a,b) for(int i=a;i>=b;--i) #define prn() printf(" ") #define prs() printf(" ") #define mkp make_pair #define pii pair<int,int> #define pub(a) push_back(a) #define pob() pop_back() #define puf(a) push_front(a) #define pof() pop_front() #define fst first #define snd second #define frt front() #define bak back() #define mem0(a) memset(a,0,sizeof(a)) #define memmx(a) memset(a,0x3f3f,sizeof(a)) #define memmn(a) memset(a,-0x3f3f,sizeof(a)) #define debug #define db double #define yyes cout<<"YES"<<endl; #define nno cout<<"NO"<<endl; #define all(i,a) for(auto i=a.begin();i!=a.end();++i) using namespace std; typedef vector<int> vei; typedef vector<pii> vep; typedef map<int,int> mpii; typedef map<char,int> mpci; typedef map<string,int> mpsi; typedef deque<int> deqi; typedef deque<char> deqc; typedef priority_queue<int> mxpq; typedef priority_queue<int,vector<int>,greater<int> > mnpq; typedef priority_queue<pii> mxpqii; typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii; const int maxn=500005; const int inf=0x3f3f3f3f3f3f3f3f; const int MOD=100000007; const db eps=1e-10; const db pi=3.1415926535; int qpow(int a,int b)int tmp=a%MOD,ans=1;while(b)if(b&1)ans*=tmp,ans%=MOD;tmp*=tmp,tmp%=MOD,b>>=1;return ans; int lowbit(int x)return x&-x; int max(int a,int b)return a>b?a:b; int min(int a,int b)return a<b?a:b; int mmax(int a,int b,int c)return max(a,max(b,c)); int mmin(int a,int b,int c)return min(a,min(b,c)); void mod(int &a)a+=MOD;a%=MOD; bool chk(int now) int half(int l,int r)while(l<=r)int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;return l; int ll(int p)return p<<1; int rr(int p)return p<<1|1; int mm(int l,int r)return (l+r)/2; int lg(int x)if(x==0) return 1;return (int)log2(x)+1; bool smleql(db a,db b)if(a<b||fabs(a-b)<=eps)return true;return false; bool bigeql(db a,db b)if(a>b||fabs(a-b)<=eps)return true;return false; bool eql(db a,db b)if(fabs(a-b)<eps) return 1;return 0; db len(db a,db b,db c,db d)return sqrt((a-c)*(a-c)+(b-d)*(b-d)); bool isp(int x)if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true; inline int read() char ch=getchar();int s=0,w=1; while(ch<48||ch>57)if(ch==‘-‘)w=-1;ch=getchar(); while(ch>=48&&ch<=57)s=(s<<1)+(s<<3)+ch-48;ch=getchar(); return s*w; inline void write(int x) if(x<0)putchar(‘-‘),x=-x; if(x>9)write(x/10); putchar(x%10+48); int gcd(int a, int b) if(a==0) return b; if(b==0) return a; if(!(a&1)&&!(b&1)) return gcd(a>>1,b>>1)<<1; else if(!(b&1)) return gcd(a,b>>1); else if(!(a&1)) return gcd(a>>1,b); else return gcd(abs(a-b),min(a,b)); int lcm(int x,int y)return x*y/gcd(x,y); int n,m,a,s[maxn]; deque<int> q; db k(int x,int y) return (s[y]-s[x]+0.0)/(y-x); signed main() ios_base::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>n>>m; re(i,1,n) cin>>a; s[i]=s[i-1]+a; db ans=-inf; re(i,m,n) #define l q.size() while(l>=2&&k(i-m,q[l-1])<k(i-m,q[l-2])) q.pob(); q.pub(i-m); while(l>=2&&k(i,q[0])<k(i,q[1])) q.pof(); ans=max(ans,k(i,q.frt)); #undef l cout<<(int)floor(ans*1000); return 0;
[洛谷u22158]策划体验(树上斜率优化)(二分最优决策)(代码片段)
题目背景 OL不在,Clao又在肝少*前线,他虽然觉得这个游戏的地图很烦,但是他认为地图的难度还是太低了,习习中作为策划还不够FM,于是他自己YY了一种新的地图和新的机制;题目描述 整个地图呈树形结构,共有N+1&nbs... 查看详情
任务安排3斜率优化dp(代码片段)
...f0c;对凸包上的点查询就不能对队首进行操作了,需要二分查找这个点,查找凸包上第一条 查看详情
浅谈带权二分或者斜率凸优化
...九省·林克卡特树》,感觉好像很热点的样子。带权二分是一类对DP的优化,对于某些最优化问题的(2d/yd)DP,通过这种优化,其效率可以达到简化后的(1d/yd)DP的效率乘一个log((xd/yd)DP是指状态数为n^x级且每种状态的转移数均... 查看详情
codeforcesround#344(div.2)e.productsum二分斜率优化dp
E.ProductSum BlakeisthebossofKris,however,thisdoesn‘tspoiltheirfriendship.Theyoftengatheratthebartotalkaboutintriguingproblemsaboutmaximisingsomevalues.Thistimetheproblemisreallyspecial.Youaregiv 查看详情
斜率优化规律
斜率单调暴力移指针斜率不单调二分找答案x坐标单调开单调队列x坐标不单调开平衡树|cdq分治——摘自MashiroSky ——ta讲解的斜率优化 查看详情
斜率优化(代码片段)
对于有i*j的项,考虑用斜率优化DP(任务安排)http://poj.org/problem?id=1180 单调递增1memset(f,8,sizeof(f));f[0]=0;2FOR(i,1,n)34while(l<r&&(f[q[l+1]]-f[q[l]])<=(sumc[q[l+1]]-sumc[q[l]])*(sumt[i]+s))++l;5f[i 查看详情
斜率优化dp学习笔记(代码片段)
...小如图:所以我们就能够通过维护下凸壳,并在下凸壳上二分来求得转移位置了补充还有一个情况,当你化成二维数点以后要求截距最大这时候你就需要维护上凸 查看详情
3156:防御准备(斜率优化)(代码片段)
链接思路 斜率优化。 f[i]表示i点建检查点的花费。 f[i]=f[j]+i*(i-j-1)-(s[i-1]-s[j])+a[i],从j转移,s为前缀和。代码1#include<cstdio>2#include<iostream>34usingnamespacestd;56typedeflonglongLL;78constintN=1000100;9LL 查看详情
hdu3507printarticle(斜率dp优化)(代码片段)
ProblemDescriptionZerohasanoldprinterthatdoesn‘tworkwellsometimes.Asitisantique,hestillliketouseittoprintarticles.Butitistoooldtoworkforalongtimeanditwillcertainlywearandtear,soZerouseacosttoevaluatet 查看详情
hdu3507printarticle(斜率优化)(代码片段)
...连续输出一段,问输出所有数的总价值最小是多少思路:斜率优化,但我不知道为什么写成slop就不对,可怜我的斜率优化板子,又要该了,其他没什么,简单的推一下是下凸包,没什么其他的了代码:#include<set>#include<map&... 查看详情
hdu3507printarticle(斜率优化)(代码片段)
PrintArticleTimeLimit:9000/3000MS(Java/Others) MemoryLimit:131072/65536K(Java/Others)TotalSubmission(s):15536 AcceptedSubmission(s):4813ProblemDescription 查看详情
『土地征用landacquisition斜率优化dp』(代码片段)
斜率优化DP的综合运用,对斜率优化的新理解。详细介绍见『玩具装箱TOY斜率优化DP』土地征用LandAcquisition(USACO08MAR)DescriptionFarmerJohnisconsideringbuyingmorelandforthefarmandhashiseyeonN(1<=N<=50,000)additionalrectangularplots,eachwithintegerdimensions(1&l... 查看详情
hdu3480division(斜率优化)(代码片段)
...平方,求m个集合的价值总和最小思路:先给出TLE代码,斜率优化下次给出,转移方程dp[i][j]=min(dp[i][j],dp[i-1][k]+(a[j]-a[k+1])*(a[j]-a[k+1]));(ps:tzw竟然说买包烟十个人,九个人都会斜率优化过题,emmm)#include<bits/stdc++. 查看详情
poj1180斜率优化dp(单调队列)(代码片段)
BatchSchedulingTimeLimit: 1000MS MemoryLimit: 10000KTotalSubmissions: 4347 Accepted: 1992DescriptionThereisasequenceofNjobstobeprocessedononemachine.Thejobsarenumberedfro 查看详情
bzoj2726:[sdoi2012]任务安排[斜率优化dp二分提前计算代价]
2726:[SDOI2012]任务安排TimeLimit: 10Sec MemoryLimit: 128MBSubmit: 868 Solved: 236[Submit][Status][Discuss]Description机器上有N个需要处理的任务,它们构成了一个序列。这些任务被标号为1到N,因此序列的排列为1 查看详情
bzoj1010[hnoi2008]玩具装箱toy(斜率优化第一题)(代码片段)
...gma的确让我看了好久思路:看了网上的很多题解,大概对斜率优化有了一点了解,发现斜率优化这种东西用在很多方面,比如在对凸壳的求解中,常用的kuangbin凸包模板中就有斜率优化的例子,对于单调队列的认识是基于某次被... 查看详情
poj1180batchscheduling-斜率优化dp(代码片段)
... 将等号左边看成纵坐标,$sumC_j$看成横坐标,$sumT_i$为斜率来进行斜率 查看详情
luogu3628特别行动队(斜率优化dp)(代码片段)
推出来式子以后斜率优化水过去就完事了1#include<cstdio>2#include<cstring>3#include<algorithm>4#include<vector>5#include<queue>6#include<cmath>7#defineinf0x3f3f3f3f8#defineLLlonglongint 查看详情