洛谷 P5665 划分
https://www.luogu.com.cn/problem/P5665
2s,1GB
Tutorial
https://www.luogu.com.cn/blog/syksykCCC/solution-p5665
假设 (sumL+x le sumR) ,那么我们将 (x) 分到那一段更优呢.
考虑 ((sum+x)^2 = sum^2+x^2+2x cdot sum) .也就是说,将其分至左边更优.
也就说,我们贪心的令最后一段尽量短即可.
设 (g_i) 表示 ([1,i]) 的最优策略中最后一段为 ((g_i,i]) .
那么我们对于 (i) ,想要找出最大的 (j) ,满足 (s_i - s_j ge s_j-s_{g_j}) 作为 (g_i) .
将式子变形得到 (s_i ge 2s_j-s_{g_j}) .那么可以用单调队列来维护 ((j,2s_j-s_{g_j})) .就可以 (O(n)) 得到 (g_i) .
然后就可以利用 (g) 求解答案了.
Code
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
inline char nc() {
// return getchar();
static char buf[100000],*l=buf,*r=buf;
return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void read(T &x) {
x=0; int f=1,ch=nc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
x*=f;
}
typedef long long ll;
const int maxn=4e7+50;
const int maxm=1e5+50;
const int base=1e9;
int n,type;
int g[maxn];
int q[maxn];
ll s[maxn],val[maxn];
void write(__int128 x) {
if(x==0) return;
write(x/10),printf("%d",int(x%10));
}
int main() {
read(n),read(type);
if(type==0) {
for(int i=1;i<=n;++i) read(s[i]),s[i]+=s[i-1];
}
else {
ll x,y,z,m,mod=1<<30;
read(x),read(y),read(z),read(s[1]),read(s[2]),read(m);
for(register int i=3;i<=n;++i) s[i]=(x*s[i-1]+y*s[i-2]+z)%mod;
for(register int j=1,i=1;j<=m;++j) {
int p,l,r; read(p),read(l),read(r),r=r-l+1;
while(i<=p) s[i]=s[i-1]+s[i]%r+l,++i;
}
}
int hd=0,tl=-1;
q[++tl]=0;
for(register int i=1;i<=n;++i) {
while(hd<tl&&val[q[hd+1]]<=s[i]) ++hd;
g[i]=q[hd],val[i]=2*s[i]-s[g[i]];
while(hd<tl&&val[q[tl]]>=val[i]) --tl;
q[++tl]=i;
}
__int128 an=0;
for(int u=n;u;u=g[u]) {
__int128 t=val[u]-s[u];
an=an+t*t;
}
write(an);
return 0;
}