UESTC 929 Post office【前缀和+贪心】

来源:互联网 发布:行爱交流软件 编辑:程序博客网 时间:2024/06/06 14:17

Post office

Problem:698

Time Limit:1000ms

Memory Limit:65536K

Description

There are N(N<=1000) villages along a straight road, numbered from 1 to N for simplicity. We know exactly the position of every one (noted pos[i],pos[i] is positive integer and pos[i]<=10^8). The local authority wants to build a post office for the people living in the range i to j(inclusive). He wants to make the sum of |pos[k]-position_of_postoffice| (i<=k<=j) is minimum. 

Input

  For each test case, the first line is n. Then n integer, representing the position of every village and in acending order. Then a integer q (q<=200000), representing the queries. Following q lines, every line consists of two integers i and j. the input file is end with EOF. Total number of test case is no more than 10.  Be careful, the position of two villages may be the same.

Output

  For every query of each test case, you tell the minimum sum.

Sample Input

31 2 321 32 30

Sample Output

21

Hint

  Huge input,"scanf"is recommend.
题目大意:


给你N个村庄的坐标,一共有Q个查询,每个查询想要在区间【i,j】之内的某个村庄建立邮局,其他村庄的村民都过来到这个点来邮寄,希望其他各个点到这个邮局的距离之和最小,问这个最小的和。

每个查询都是独立的。


思路:

很显然,我们在区间【i,j】之内建立一个邮局,我们希望其他各个点到这个点的距离之和最小,那么这个邮局需要尽可能的在中间部位建成。


①当区间内点的个数为奇数的时候,建立邮局就在中间点。

②当区间内点的个数为偶数的时候,建立邮局在中间的两个点之中的任意一个点,取最小值。


那么我们如果暴力做的话,时间复杂度会达到O(qn);

所以我们这里再维护一个前缀和,就能做到O(q)了;


Ac代码:

#include <bits/stdc++.h>typedef long long int ll;using namespace std;int n;ll sum[150000];ll a[150000];int main(){    while(~scanf("%d",&n))    {        for(int i=0;i<n;i++)scanf("%lld",&a[i]);        for(int i=0;i<n;i++)        {            if(i==0)sum[i]=a[i];            else sum[i]=sum[i-1]+a[i];        }        int q;        scanf("%d",&q);        while(q--)        {            int x,y;            scanf("%d%d",&x,&y);            x--;            y--;            if((y-x+1)%2==1)            {                int mid=(x+y)/2;                ll num=(y-x+1)/2;                ll output=a[mid]*num-(sum[mid-1]-sum[x-1]);                output+=(sum[y]-sum[mid])-a[mid]*num;                printf("%lld\n",output);            }            else            {                int mid=(x+y)/2;                ll num=(y-x+1)/2-1;                ll output=a[mid]*num-(sum[mid-1]-sum[x-1]);                output+=(sum[y]-sum[mid])-a[mid]*(num+1);                mid=(x+y)/2+1;                num=(y-x+1)/2;                ll output2=a[mid]*num-(sum[mid-1]-sum[x-1]);                output2+=(sum[y]-sum[mid])-a[mid]*(num-1);                printf("%lld\n",min(output,output2));            }        }    }}





原创粉丝点击