焦作区域赛 distance(思维+贪心)

There are n points on a horizontal line, labelled with 1 through n from left to right.

有n个点在一条水平线上,从左到右以1到n标号

The distance between the i-th point and the (i+1)-th point is ai.

点i+1与点i的距离为ai

For each integer k ranged from 1 to n, you are asked to select exactly k different given points on the line to maximize the sum of distances between all pairs of selected points.

对于每个范围在1到n之间的整数k,要求你去选择线上k个不同的给定的点以最大化他们每一对之间的距离之和。

Input

The input contains several test cases, and the first line contains a positive integer TT indicating the number of test cases which is up to 1000.

For each test case, the first line contains an integer nn indicating the number of points, where 2≤n≤1052≤n≤105.

The second line contains (n−1)(n−1) positive integers a1,a2,⋯,an−1a1,a2,⋯,an−1, where 1≤ai≤1041≤ai≤104.

We guarantee that the sum of nn in all test cases is up to 106106.

Output

For each test case, output a line containing nn integers, the ii-th of which is the maximum sum of distances in case k=ik=i. You should output exactly one whitespace between every two adjacent numbers and avoid any trailing whitespace in this line.

Example

input

Copy

1
5
2 3 1 4

output

Copy

0 10 20 34 48

Note

The figure below describes the sample test case.  下面的图解释了样例

焦作区域赛 distance(思维+贪心)_第1张图片

The only best selection for k=2 should choose the leftmost and the rightmost points, while a possible best selection for k=3 could contain any extra point in the middle.

k=2时唯一的最优选择应该是选择最左和最右的点,同时对于k=3的最优解应该选择左右两点之间中间的任意点

对于这张图,我们找一下规律(设图中点从左到右为1-5号点)

k=1时,本次选择点1,已选择点1,总距离sum=0

k=2时,本次选择点5,已选择点1,5,总距离sum=10

k=3时,本次选择点2(2,4都一样),已选择点1,2,5,总距离sum=20

k=4时,本次选择点3,已选择点1,2,3,5,总距离sum=34

k=5时,总距离sum=48

我们可以看到,按照这种方案奇数次选点时,总距离都会加上包含这个点的上一个最大区间的距离值,偶数次选点时,是加上最大区间距离值的同时加上这个点与上一次选点的距离。

那么我们设计一个这样的策略:设定两个指针进行两边夹。

#include 
#include 
#include 
#include 
#include 
#include 
#define DETERMINATION main
#define lldin(a) scanf("%lld",&a)
#define din(a) scanf("%d",&a)
#define printlnlld(a) printf("%lld\n",a)
#define printlnd(a) printf("%d\n",a)
#define printlld(a) printf("%lld",a)
#define printd(a) printf("%d",a)
#define reset(a,b) memset(a,b,sizeof(a))
const int INF=0x3f3f3f3f;
using namespace std;
const double PI=acos(-1);
typedef long long ll;
typedef long double ld;
const int MOD=10000;
///Schlacht von Stalingrad
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
ll a[750000];
int DETERMINATION()
{
    ll t;
    lldin(t);
    while(t--)
    {
        ll n;
        lldin(n);
        ll tmp=0,sum=0;
        a[1]=0;
        for(int i=2;i<=n;i++)
            {
                lldin(tmp);
                sum+=tmp;
                a[i]=sum;
            }
        ll increment=0,ans=0;//每次的增量(目前最大区间长度)与总答案
        ll pointerh=1,pointert=n;//两个指针
        for(int i=1;i<=n;i++)
        {
            if(i&1)
                ans+=increment;//奇数次选点直接加上这个增量
            else
            {
                increment+=sum;//增量(这个sum是上面输入时统计的最大距离)
                ll d1=a[pointert]-a[pointert-1];//区间右侧修剪
                pointert--;
                ll d2=a[pointerh+1]-a[pointerh];//区间左侧修剪
                pointerh++;
                sum=sum-d1-d2;//修改区间
                ans+=increment;
            }
            if(i==1)
            printf("%lld",ans);
            else
            printf(" %lld",ans);
        }
        printf("\n");
    }
    return 0;
}

 

你可能感兴趣的:(贪心算法)