p1404平均数(二分/斜率优化)(代码片段)

oneman233 oneman233     2023-05-08     678

关键词:

先说说二分的思路:

对数列中每个数字都减去当前二分的答案,然后求出前缀和,如果前缀和在某个位置加上前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 查看详情