タイトル
思考
パート1分(36)
まず、それはDPを考えることは容易である
\(dp_ {I、J} \)号に前駆体を示すノードi jはれる
転送も非常に簡単である\(dp_ {I、J} = MIN_ {k = 1} ^ {J-1} DP [K] [J-1]
+(S [i]を-s [J-1])^ 2 \) もちろん確実に転送することパート2分(64)
DPは直接のために最適化されています
それは、Jを見つけるのは簡単です、私達はちょうど見つける必要がある\(MIN_は{私は1 =} ^ {J-1} DP [I] [J-1] \) の行に
この値を用いて、ミネソタ州バックに転送することができ
正解
デバッグの過程で、
我々は、パターンを見つけた\(dp_ {I、J} <= dp_ {I、K}(K <= J)\)
もちろん、この結論は、著者を証明していません
しかし、感情的な理解
最小の最後の段落、
可能な限り小さく各セクションの前の手段、
できるだけ小さな手段として、各セクションの前に、各セグメントの小さい正方形
すなわち、もし\(X_1 + X_2 == Y_1 + Y_2 + y_3 \)
\(X_1、X_2 \)なるべく等しいものとして、\(Y_1、Y_2、Y_3 \)できるだけ等しいとして
\(X_1 * X_1 + X_2 * X_2> = Y_1 * Y_1 + Y_2 * Y_2 + y_3 * y_3 \)
これは、シーケンスのために、あります
シーケンス全体の最後のセグメントの最適な長さは、長さの全ての溶液の最小でなければなりません
$のdp_ {I、J} $が良くなる方法を考えてみましょう
まず、それは私が最も近いJ jのでなければなりません、
その後、我々はすぐに見つける方法を検討してください\(MIN_ {K = 1} ^ {J-1} {dp_ J-1、K} \)
k個のJ-1の最も近くもkのでなければなりません
私たちは、DPを再定義することができます
\(dp_i \) I先行ノードのノード番号があると述べました
どのように転送考えてみましょう
iはノードiの最大数に転送することができるノードの数、ノード1からのDP値
そうすることができます(dp_i \)\節転移を有するラインで何が法律では、
転送ノードセットがKであります
\(S_K-S_ {dp_k} <= S_I-S_K \)
\(2 * S_K-S_ {dp_k} <= S_I \)
この式を通じて簡単に単調なキューの最適化を考えることができます
ビッグベンによって検査室の時にこの質問の傾きを最適化することにより誇ってきた、自己テストが0であると思われますコード
私は怠け者だったので
実際には、あまりにも多くの食べ物直接__int128と
リマインダー、CSPは__int128できません
そして、この正規のカードの質問はほとんどビットとカードスペース
#include<iostream> #include<cstdio> #include<queue> using namespace std; const int mod=(1ll<<30); void read(__int128 &x) { x=0; int f=1; char c=getchar(); while('0'>c||c>'9') { if(c=='-') f=-1; c=getchar(); } while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } x*=f; } void read(long long &x) { x=0; int f=1; char c=getchar(); while('0'>c||c>'9') { if(c=='-') f=-1; c=getchar(); } while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } x*=f; } void read(int &x) { x=0; int f=1; char c=getchar(); while('0'>c||c>'9') { if(c=='-') f=-1; c=getchar(); } while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } x*=f; } void write(__int128 x) { if(x>9) write(x/10); putchar(x%10+'0'); } struct node { int p; int l; int r; }fff[100005]; int n,ty; int hea=1; int tai=1; int now; int q[40000005]; int dp[40000005]; long long s[40000005]; int a[40000005]; int b[40000005]; __int128 ans; __int128 basic=1; long long x,y,z,m; long long solve_mon(int i) { return 2*s[i]-s[dp[i]]; } int main() { read(n); read(ty); if(ty==0) { for(int i=1;i<=n;i++) { read(a[i]); s[i]=s[i-1]+a[i]; } } else { read(x); read(y); read(z); read(b[1]); read(b[2]); read(m); for(int i=1;i<=m;i++) { read(fff[i].p); read(fff[i].l); read(fff[i].r); } for(int i=3;i<=n;i++) b[i]=(x*b[i-1]%mod+y*b[i-2]%mod+z)%mod; for(int j=1;j<=m;j++) for(int i=fff[j-1].p+1;i<=fff[j].p;i++) { a[i]=(b[i]%(fff[j].r-fff[j].l+1))+fff[j].l; s[i]=s[i-1]+a[i]; } } for(int i=1;i<=n;i++) { while(hea<tai&&solve_mon(q[hea+1])<=s[i]) hea++; dp[i]=q[hea]; while(hea<tai&&solve_mon(q[tai])>=solve_mon(i)) tai--; q[++tai]=i; } now=n; while(now) { ans+=basic*(s[now]-s[dp[now]])*((s[now]-s[dp[now]])); now=dp[now]; } write(ans); return 0; }