1. 程式人生 > 實用技巧 >BZOJ-1811 [Ioi2005]mea(解方程)

BZOJ-1811 [Ioi2005]mea(解方程)

題目描述

  考慮一個非遞減的整數序列 \(S_1,\cdots,S_{n+1}(S_i \leq S_{i+1},1\leq i\leq n)\)。序列 \(M_1 \cdots M_n\) 是定義在序列 \(S\) 的基礎上,關係式為 \(M_i=\frac{S_i+S_{i+1}}{2}(1\leq i<n)\),序列 \(M\) 叫做序列 \(S\) 的平均數序列。

  例如序列 \(1,2,2,4\) 的平均數序列為 \(1.5,2,3\)。注意到平均數序列中的元素可能為小數。但是本題的任務只是處理平均數序列都為整數的情況。

  給出一個 \(n\) 個數字的非遞減的整數序列 \(M_1,M_2,\cdots,M_n\)

。請你計算出:序列 \(S_1,\cdots,S_{n+1}\) 的平均序列是 \(M_1,\cdots,M_n\)。求滿足以上條件的序列 \(S\) 的總個數。

  資料範圍:\(2\leq n\leq 5\times 10^6,1\leq M_i\leq 10^9\)

分析

  只要確定了序列第一個數字 \(S_1\),則其他 \(S_i\) 都可以用含 \(S_1\) 的式子表示出來,設 \(S_1=x\)

\[\begin{aligned}&S_1=x\\&S_2=2M_1-S_1=2M_1-x\\&S_3=2M_2-S_2=2(-M_1+M_2)+x\\&S_4=2M_3-S_3=2(M_1-M_2+M_3)-x\\&\cdots\\&S_{i-1}=2M_{i-2}-S_{i-2}=2(-M_1+M_2-\cdots+M_{i-2})+x\\&S_i=2M_{i-1}-S_{i-1}=2(M_1-M_2+M_3-\cdots+M_{i-1})-x(i為偶數)\end{aligned} \]

  由於 $S_i\leq S_{i+1}(1\leq i\leq n) $,可以列出以下 \(n\) 個不等式(設 \(c_i=M_1-M_2+\cdots-M_{i}\)):

\[\begin{aligned}&S_1\leq S_2\Longrightarrow x\leq M_1\\&S_2\leq S_3\Longrightarrow 2M_1-M_2\leq x\\&S_3\leq S_4\Longrightarrow x\leq 2M_1-2M_2+M_3\\&\cdots\\&S_{i-1}\leq S_{i}\Longrightarrow x\leq 2c_{i-2}+M_{i-1}\\&S_{i}\leq S_{i+1}\Longrightarrow 2c_{i-1}-M_{i}\leq x(i為偶數)\end{aligned} \]

  維護 \(L=\max(L,2c_{i-1}-M_i)(i\%2=0),R=\min(R,2c_{i-1}+M_i)(i\%2=1)\),答案為 \(\max(R-L+1,0)\)

程式碼

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
const int N=5e6+10;
long long c[N],M[N];
int main()
{
    int n=read();
    long long L=-1ll<<60,R=1ll<<60,ans=0;
    for(int i=1;i<=n;i++)
    {
        M[i]=read();
        if(i%2==1)
            ans=ans+M[i];
        else
            ans=ans-M[i];
        c[i]=ans;
    }
    for(int i=1;i<=n;i++)
    {
        if(i%2==1)
            R=min(R,2*c[i-1]+M[i]);
        else
            L=max(L,2*c[i-1]-M[i]);
    }
    //cout<<L<<" "<<R<<endl;
    cout<<max(R-L+1,0ll)<<endl;
    return 0;
}