[jzoj5236]【NOIP2017模擬8.7A組】利普希茨

這道像數據結構的結論題傳送門

我覺得這斷不能怪我 一上來給出操作種類和 Log 形式的數據範圍有如套路一般


Solution

60p

容易想到分治

對於整個序列,可以割作三份,分界點爲最大值和最小值

因爲 如果有一個 (i,j) 跨過了 分界點 k 那麼 (i,k)|(k,j) 會是更優的決策

然鵝,分界點因而要合法地被算入每個區間,所以處理詢問複雜度是 Log2n

100p

觀察樣例,或是其他詭異的方式,可以斷定:答案的 (i,j) 一定滿足 j=i+1 即兩者相鄰時最優

我們假設 下圖中的 (a,b) 優於 (a,c)(c,b)

L

如果 a,c,b 不滿足遞增 那麼與假設不符

故設 a>c>b

那麼一定有

abx+1+y+1>acx+1

abx+1+y+1>cby+1

既然都是正數 我們簡單處理 容易得到

(ab)(x+1)>(ac)(x+1+y+1)

(ab)(y+1)>(cb)(x+1+y+1)

兩式相加 (ab)(x+1+y+1)>(ab)(x+1+y+1)

矛盾 所以 (a,c)(c,b) 優於 (a,b)

所以越小的區間由於越大的區間 得出結論

Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define oo 2139062143
#define sqr(x) ((x)*(x))
#define lowbit(x) ((x)&(-x))
#define abs(x) (((x)>=0)?(x):(-(x)))
#define max(x,y) (((x)>(y))?(x):(y))
#define min(x,y) (((x)<(y))?(x):(y))
#define fo(i,x,y) for (ll i = (x);i <= (y);++ i)
#define fd(i,x,y) for (ll i = (x);i >= (y);-- i)
using namespace std;
typedef double db;
typedef long long ll;
const ll N = 100100;
ll n,d[N * 4],a[N],q;
ll type,l,r;
ll bit;
void build(ll n)
{
    for(bit=1;bit<=n+1;bit<<=1);//bit = 總節點數目 - 葉子節點數目
    for(ll i=bit+1;i<=bit+n;i++) d[i] = abs(a[i - bit + 1] - a[i - bit]);
        // scanf("%d",&d[i]);
    for(ll i=bit-1;i;i--)
        d[i]=max(d[i<<1],d[i<<1|1]);
}
void updata(ll x,ll y)//修改 d[x] 爲 y
{
    for(d[x+=bit]=y,x>>=1;x;x>>=1)
        d[x]=max(d[x<<1],d[x<<1|1]);
}
ll query(ll s,ll t)//區間 [s,t] 最大值
{
    ll ans=0;
    for(s+=bit-1,t+=bit+1;s^t^1;s>>=1,t>>=1)
    {
        if(~s&1) ans=max(ans,d[s^1]);
        if(t&1) ans=max(ans,d[t^1]);
    }
    return ans;
}
ll read()
{
    char ch=' ';ll q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;
    ll n=q*w;return n;
}
ll buf[30];
void write(ll x)
{
    if (x<0) putchar('-'),x=-x;
    buf[0]=0;
    while (x) buf[++buf[0]]=x%10,x/=10;
    if (!buf[0]) buf[0]=1,buf[1]=0;
    while (buf[0]) putchar('0'+buf[buf[0]--]);
}
int main()
{
     freopen("lipschitz.in","r",stdin);
     freopen("lipschitz.out","w",stdout);
    n = read();
    fo(i,1,n) a[i] = read();
    build(-- n);
    q = read();
    while (q --)
    {
        type = read(),l = read(),r = read();
        if (type == 0)
        {
            a[l] = r;
            updata(l,abs(a[l + 1] - a[l]));
            updata(l - 1,abs(a[l] - a[l - 1]));
            continue;
        }
        write(query(l,r - 1));putchar('\n');
    }
}
發佈了162 篇原創文章 · 獲贊 297 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章