修建传送门 | ||||||
| ||||||
Description | ||||||
做为长城上的卫士,影踪派一直守在螳螂高原上防止螳螂人卡拉克西的入侵。影踪派的长城可以近似看做是一条直线上依次编号为1~N的N个基地组成,编号相邻的两个基地之间由长城相连接,而影踪派掌门祝踏岚所在的影踪禅院位于编号为1的基地。 | ||||||
Input | ||||||
第一行为一个正整数T,表示测试数据组数。 每组测试数据第一行为一个整数N(1 <= N <= 100000),第二行包含N-1个正整数,其中第i个数表示编号为i的基地与编号为i+1的基地之间的长城长度。此长度不会超过2147483647. | ||||||
Output | ||||||
对每组测试数据输出一行,仅含一个整数,表示按照最优方案建造完虫洞后,祝踏岚需要从基地1赶到的移动距离最远的基地的移动距离。 | ||||||
Sample Input | ||||||
2 3 1 20 6 1 2 3 4 5 | ||||||
Sample Output | ||||||
1 5 | ||||||
Source | ||||||
2016级新生程序设计全国邀请赛 |
思路:
1、部分思路参考自:http://www.cnblogs.com/xingkongyihao/p/6105717.html....
2、首先我们这么想,建造传送阵的意义是什么?明显是为了缩减从起点到最远点的距离。
紧接着,还能够缩减从起点到其他各个点的距离。
那么我们如果将这个传送阵放到距离起点X远处,那么我们从起点到传送门再到其他各个点就有一个起步长度。很显然我们希望没有这个起步长度。那么想到,将第一个传送阵放到原点(出发点。)
3、接下来我们就可以O(n)枚举第二个传送阵的点,那么接下来考虑此时最短路最长可能的情况:
①从传送阵到最后一个点的长度。
②从起点到的一个点Z
③以及这个点Z到第二个传送阵的距离。
那么我们考虑如何维护②和③....(暴力处理时间复杂度会达到O(n^2)......好鸡肋啊,下边这句话想到了就不至于卡了俩小时啦T T)
我们很明显想要将这两个长度使其尽可能的接近。那么我们维护一个变量j,使得其保证sum【j】>sum【i】-sum【j】&&sum【j-1】<=sum【i】-sum【j-1】;
那么这个点j就是上述过程中的点Z.
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define ll long long int
ll a[100050];
ll sum[100050];
ll ans;
int n;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(sum,0,sizeof(sum));
for(int i=2;i<=n;i++)scanf("%lld",&a[i]);
for(int i=2;i<=n;i++)sum[i]=sum[i-1]+a[i];
ans=600000000000000000;
ll tmp=0;
int j=1;
for(int i=1;i<=n;i++)
{
while(j<i&&sum[j]<=sum[i]-sum[j])
{
j++;
}
tmp=max(sum[i]-sum[j],sum[j-1]);
tmp=max(sum[n]-sum[i],tmp);
if(tmp<ans)
{
ans=tmp;
}
}
printf("%lld\n",ans);
}
}