题目 http://uoj.ac/problem/244
orz myy
这个矩形对称的性质非常优美, 所以我们只需要考虑一个 \(\frac{1}{4}\) 的矩阵, 即一个倒三角形
现在我们要求的是从 \((1,1)\) 到三角形对边上每个点的最短路, 不难发现如果一个某一行不是前缀最小值那么一定不可能成为最优答案, 我们可以直接从上面一行跑掉而不走这一行
于是我们的路径就是一些 \(L\) 形拼了起来, 对于非前缀最小行我们只可能经过上面的一个点; 正确性比较好理解, 我们可以通过在上一个前缀最小行多经过一些点来代替
所以我们的策略肯定是在一个前缀最小行往右边走, 直到恰好能到达下一个前缀最小行的时候再向下走, 于是每一个前缀最小行经过的点数是于下一个前缀最小行之间的距离, 而中间的非前缀最小行都只会被经过一次
代码
- #include<bits/stdc++.h>
- #define re register
- #define LL long long
- #define min(a,b) ((a)<(b)?(a):(b))
- inline int read() {
- char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
- while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
- }
- const int maxn=1e5+5;
- int a[maxn],n,st[maxn],top;LL ans,nw,sum;
- inline int calc(int x) {return 2ll*n-1-2ll*(n-x)-1;}
- int main() {
- n=read()+1;for(re int i=1;i<=n;i++) a[i]=read();
- ans=1ll*a[n]*(4ll*(n-1)-3);st[top=1]=n;sum=a[n]+a[n];
- for(re int i=n-1;i;i--) {
- sum+=a[i]+a[i];if(a[i]>=a[st[top]]) continue;
- nw+=2ll*(st[top]-i)*a[st[top]];
- ans=min(ans,nw+sum+2ll*a[i]*calc(i)-a[i]);
- st[++top]=i;
- }
- printf("%lld\n",ans);
- return 0;
- }
来源: http://www.bubuko.com/infodetail-3279644.html