总结
这个题有三种方法写,线段树跟倍增算法其实都差不多,这个题如果用线段树写,就麻烦了,毕竟是离线状态求值,所以单调队列跟倍增更好吧,线段树的代码确实不少,码的话,挺难受的。
解析
pre[i]表示以i结尾的前缀和
p[i]表示以i结尾的子区间的最大和区间和
p[i]=max(pre[i]-pre[j]) max(0,i-k) <= j <= i-1
变形一下:p[i]=pre[i]-min(pre[j]);
这里不就是求得区间最值的问题,离线状态,一次查询,单调队列刚好满足。
题目链接
倍增写法
/*
____________ ______________ __
/ _________ /\ /_____ _____/\ / /\
/ /\ / / \\ / /\ \ \ / / \
/ / \_____/ / / \__/ / \____\/ / / /
/ / / / / / / / / / / /
/ / / / / / / / / / / /
/ / / / / / / / / / / /
/ /___/____/ / / / / / / /___/________
/____________/ / /__/ / /______________/\
\ \ / \ \ / \ \ \
\____________\/ \__\/ \______________\/
___ ___ ___ __________
/ /\ / /\ / /\ /_______ /\
/ /__\___/ / \ / / \ \ / / \
/____ ____/ / / / / \____/ / /
\ / /\ \ / / / / / / /
\_/ / \___\/ ___ / / / / / /
/ / / / /\ / / / / / /
/ / / / /__\__/ / / / /___/____
/___/ / /___________/ / /___________/\
\ \ / \ \ / \ \ \
\___\/ \___________\/ \___________\/
A CODE OF CBOY
*/
#include<bits/stdc++.h>
//typedef long long ll;
//#define ull unsigned long long
//#define int long long
#define F first
#define S second
#define endl "\n"//<<flush
#define eps 1e-6
#define lowbit(x) (x&(-x))
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define MAXN 0x7fffffff
#define INF 0x3f3f3f3f3f3f3f3f
#define pa pair<int,int>
#define ferma(a,b) pow(a,b-2)
#define pb push_back
#define all(x) x.begin(),x.end()
#define memset(a,b) memset(a,b,sizeof(a));
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
void file()
{
#ifdef ONLINE_JUDGE
#else
freopen("cin.txt","r",stdin);
// freopen("cout.txt","w",stdout);
#endif
}
const int N=5e5+5;
int a[N],pre[N];
struct RMQ
{
vector<vector<int> >ST;
RMQ(int n=0)
{
ST.resize(n+1,vector<int>(21,inf));
for(int i=1;i<=n;i++)
ST[i][0]=pre[i];
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j+(1<<i)-1<=n;j++)
ST[j][i]=min(ST[j][i-1],ST[j+(1<<i-1)][i-1]);
}
int query(int l,int r)
{
int k=log2(r-l+1);
return min(ST[l][k],ST[r-(1<<k)+1][k]);
}
};
signed main()
{
IOS;
//file();
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i],pre[i]=pre[i-1]+a[i];
RMQ st(n);
int ans=-inf;
for(int i=1;i<=n;i++)
{
int l=max(0,i-m),r=i-1;
ans=max(ans,pre[i]-st.query(l,r));
}
cout<<ans<<endl;
return 0;
}
线段树写法
/*
____________ ______________ __
/ _________ /\ /_____ _____/\ / /\
/ /\ / / \\ / /\ \ \ / / \
/ / \_____/ / / \__/ / \____\/ / / /
/ / / / / / / / / / / /
/ / / / / / / / / / / /
/ / / / / / / / / / / /
/ /___/____/ / / / / / / /___/________
/____________/ / /__/ / /______________/\
\ \ / \ \ / \ \ \
\____________\/ \__\/ \______________\/
___ ___ ___ __________
/ /\ / /\ / /\ /_______ /\
/ /__\___/ / \ / / \ \ / / \
/____ ____/ / / / / \____/ / /
\ / /\ \ / / / / / / /
\_/ / \___\/ ___ / / / / / /
/ / / / /\ / / / / / /
/ / / / /__\__/ / / / /___/____
/___/ / /___________/ / /___________/\
\ \ / \ \ / \ \ \
\___\/ \___________\/ \___________\/
A CODE OF CBOY
*/
#include<bits/stdc++.h>
//typedef long long ll;
//#define ull unsigned long long
//#define int long long
#define F first
#define S second
#define endl "\n"//<<flush
#define eps 1e-6
#define lowbit(x) (x&(-x))
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define MAXN 0x7fffffff
#define INF 0x3f3f3f3f3f3f3f3f
#define pa pair<int,int>
#define ferma(a,b) pow(a,b-2)
#define pb push_back
#define all(x) x.begin(),x.end()
#define memset(a,b) memset(a,b,sizeof(a));
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
void file()
{
#ifdef ONLINE_JUDGE
#else
freopen("cin.txt","r",stdin);
// freopen("cout.txt","w",stdout);
#endif
}
const int N=5e5+5;
int a[N],pre[N];
///注意1:add(0,0,n,x,v)
///注意2:sum(0,0,n,x,y)区间和[x,y]
///注意3:记得空间初始化为n就可以了,内部自动开辟4n空间
struct SegmentTree
{
vector<int>vec;
SegmentTree(int n=0)
{
vec.resize(n<<2,inf);
}
void up(int p)
{
vec[p]=min(vec[p*2+1],vec[p*2+2]);
}
void add(int p,int l,int r,int x,int v)
{
if(l==r)
{
vec[p]=v;
return ;
}
int mid=(l+r)>>1;
if(x<=mid)
add(p*2+1,l,mid,x,v);
else
add(p*2+2,mid+1,r,x,v);
up(p);
}
int sum(int p,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
return vec[p];
int mid=(l+r)>>1,res=inf;
if(x<=mid)
res=min(res,sum(p*2+1,l,mid,x,y));
if(mid<y)
res=min(res,sum(p*2+2,mid+1,r,x,y));
return res;
}
};
signed main()
{
IOS;
//file();
int n,m;
cin>>n>>m;
SegmentTree st(n);
st.add(0,0,n,0,0);
for(int i=1;i<=n;i++)
cin>>a[i],pre[i]=pre[i-1]+a[i],st.add(0,0,n,i,pre[i]);
int ans=-inf;
for(int i=1;i<=n;i++)
{
int l=max(0,i-m),r=i-1;
ans=max(ans,pre[i]-st.sum(0,0,n,l,r));
}
cout<<ans<<endl;
return 0;
}
单调队列
/*
____________ ______________ __
/ _________ /\ /_____ _____/\ / /\
/ /\ / / \\ / /\ \ \ / / \
/ / \_____/ / / \__/ / \____\/ / / /
/ / / / / / / / / / / /
/ / / / / / / / / / / /
/ / / / / / / / / / / /
/ /___/____/ / / / / / / /___/________
/____________/ / /__/ / /______________/\
\ \ / \ \ / \ \ \
\____________\/ \__\/ \______________\/
___ ___ ___ __________
/ /\ / /\ / /\ /_______ /\
/ /__\___/ / \ / / \ \ / / \
/____ ____/ / / / / \____/ / /
\ / /\ \ / / / / / / /
\_/ / \___\/ ___ / / / / / /
/ / / / /\ / / / / / /
/ / / / /__\__/ / / / /___/____
/___/ / /___________/ / /___________/\
\ \ / \ \ / \ \ \
\___\/ \___________\/ \___________\/
A CODE OF CBOY
*/
#include<bits/stdc++.h>
//typedef long long ll;
//#define ull unsigned long long
//#define int long long
#define F first
#define S second
#define endl "\n"//<<flush
#define eps 1e-6
#define lowbit(x) (x&(-x))
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define MAXN 0x7fffffff
#define INF 0x3f3f3f3f3f3f3f3f
#define pa pair<int,int>
#define ferma(a,b) pow(a,b-2)
#define pb push_back
#define all(x) x.begin(),x.end()
#define memset(a,b) memset(a,b,sizeof(a));
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
void file()
{
#ifdef ONLINE_JUDGE
#else
freopen("cin.txt","r",stdin);
// freopen("cout.txt","w",stdout);
#endif
}
const int N=5e5+5;
int pre[N];
signed main()
{
IOS;
//file();
int n,m;
cin>>n>>m;
deque<int>de;
int ans=-inf;
for(int i=1;i<=n;i++)
{
int x;
cin>>x,pre[i]=pre[i-1]+x;
while(!de.empty()&&de.front()<i-m)de.pop_front();
int pos=(de.empty()?0:de.front());
ans=max(ans,pre[i]-pre[pos]);
while(!de.empty()&&pre[de.back()]>=pre[i])de.pop_back();
de.push_back(i);
}
cout<<ans<<endl;
return 0;
}