[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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章