bzoj 2216 [Poi2011]Lightning Conductor 决策单调性

本文探讨了一种利用决策单调性的算法优化技巧,通过实例分析展现了如何在特定问题中运用决策单调性降低复杂度,实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

已知一个长度为n的序列a1,a2,…,an。
对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt(abs(i-j))
Input
第一行n,(1<=n<=500000)
下面每行一个整数,其中第i行是ai。(0<=ai<=1000000000)

Output
n行,第i行表示对于i,得到的p

Sample Input
6

5

3

2

4

2

4

Sample Output
2

3

5

3

5

4

HINT


传送门
……并不会写。。后面看代码还真是神了。。
题目要求的东西转化一下,其实就是求一个最小的整数p,满足:
aj+abs(ij)ai<=p
于是令f(i)为对于i的答案,那么
f(i)=max{aj+abs(ij)}ai
考虑一下去掉绝对值,这只要先正着来一遍,再倒着来一遍就好了。
那么假如说是正着来的,也就是假设 j<i
对于决策 k<j<i ,j比k优,那么
aj+ij>ak+ik
考虑i后移,比如i->i+1,那么两者变化为:
aj+i+1jak+i+1k
变化量各自是
i+1jiji+1kik
由于 j>k 所以 xj<xk ,而 f(i)=i 是一个上凸函数,
所以说变化量里,j的变化量>k的变化量,
所以就是说!k完全没用啦!
随着i的后移,决策点一定是单调移动的……这就是“决策单调性”
涨姿势了。。。啥?泥问我为啥是单调移动的?……
如果j比k优了k就没用了。。如果k比j优那还有点戏。。
所以如果当前决策点为pos,pos及之前的点都没用了,
要么不移动,往后移动的话,pos肯定也没用了……很容易yy的辣!

于是这个显而易见(……划掉)的决策单调性就出来了,
那么对于i,i之前的所有点决策点肯定<=i决策点,
i之后所有点决策点肯定>=i决策点。。
于是就出来了个整体二分的样子。。或者说框架?
就是记录当前决策点区间,还有当前处理的区间,
最坏 T(n)=2T(n/2)+O(n)O(nlogn)
这个写法实在是太神了……我队列yy了半年都无果QAQ……

#include<bits/stdc++.h>
using namespace std;
const int 
    N=500005;
int n,a[N],f[N];
void solve(int L,int R,int l,int r,bool flag){
    if (l>r) return;
    int pos=0,mid=(l+r)>>1;
    if (!flag && mid==1) return;
    if (flag && mid==n) return;
    double MAX=0.0;
    if (!flag){
        int t=min(R,mid-1);
        for (int i=L;i<=t;i++)
            if ((double)sqrt(mid-i)+a[i]>MAX)
                MAX=(double)sqrt(mid-i)+a[i],pos=i;
    } else{
        int t=max(L,mid+1);
        for (int i=t;i<=R;i++)
            if ((double)sqrt(i-mid)+a[i]>MAX)
                MAX=(double)sqrt(i-mid)+a[i],pos=i;
    }
    f[mid]=max(f[mid],(int)ceil(MAX)-a[mid]);
    solve(L,pos,l,mid-1,flag);
    solve(pos,R,mid+1,r,flag);
}
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    solve(1,n,1,n,0),solve(1,n,1,n,1);
    for (int i=1;i<=n;i++)  printf("%d\n",f[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值