時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld
題目描述 張經理的公司的辦公室長達100000米,從最左端開始每間隔1米都有一個工位(從第1米開始有工位),位於第i米的工位稱爲i號工位,且這些工位都在一條水平線上。他有n個員工,每個員工分別位於xi號工位上(不同員工可能位於同一個工位)。
現在張經理想把員工聚集在某兩個工位上,他有q套方案(每套方案包含兩個工位號,兩個工位號可能相同),他想知道對於每套方案,所有員工都到達兩個工位中的某一個所需走的最短路徑之和是多少。輸入描述:第一行輸入兩個正整數n, q
第二行輸入n個正整數xi,分別代表第i個員工的工位
之後q行每行輸入兩個整數a,b,代表該套方案要求的兩個集合位置
(1<=n,q,xi,a,b<=10^5)(1<=n,q,xi,a,b<=105)輸出描述:對於每套方案,輸出一個整數代表答案,每個答案獨佔一行。
示例1
輸入
3 2
1 3 5
1 4
2 1
輸出
2
4
——————————————————————————————————————————————
比賽的時候沒寫出來,果然還是太菜了
思路是前綴和加預處理距離,但是判斷寫的太過於複雜把自己繞進去了,沒想到後綴和處理
思路:有AB兩點,小於等於A的去A,大於B的去B,小於等於[(A+B)/2]的去A,大於的去B;
輸入數據後,進行前綴後綴處理:
前綴
size_t sumx=0;
int sumn=0;
for(int i=0;i<nmax;++i)
{
if(key[i])
{
sumx+=key[i]*i;//小於等於i位置的員工座標和
sumn+=key[i];//位置小於等於i的人數
}
x[i]=sumx;
num[i]=sumn;
}
後綴
sumx=0;
sumn=0;
for(int i=nmax-1;i>=0;--i)
{
X[i]=sumx;
NUM[i]=sumn;
if(key[i])
{
sumx+=key[i]*i;
sumn+=key[i];
}
}
處理完後
size_t avb=(a+b)/2;
sum+=num[a]*a-x[a];//小於a
sum+=X[b]-NUM[b]*b;//大於b
sum+=(NUM[avb]-NUM[b])*b-X[avb]+X[b];//中點右
sum+=x[avb]-x[a]-(num[avb]-num[a])*a;//中點左
AC碼:
#include<bits/stdc++.h>
#define nmax 100001
using namespace std;
size_t x[100001]={0};
size_t X[100001]={0};
int key[100001]={0};
int num[1000001]={0};
int NUM[100001]={0};
int main()
{
int n,q;
cin>>n>>q;
for(int i=0;i<n;++i)
{
int tmp;
cin>>tmp;
key[tmp]++;
}
size_t sumx=0;
int sumn=0;
for(int i=0;i<nmax;++i)
{
if(key[i])
{
sumx+=key[i]*i;//小於等於i位置的員工座標和
sumn+=key[i];//位置小於等於i的人數
}
x[i]=sumx;
num[i]=sumn;
}
sumx=0;
sumn=0;
for(int i=nmax-1;i>=0;--i)
{
X[i]=sumx;
NUM[i]=sumn;
if(key[i])
{
sumx+=key[i]*i;
sumn+=key[i];
}
}
while(q--)
{
size_t sum=0;
size_t c,d;
cin>>c>>d;
size_t a,b;
a=min(c,d);
b=max(c,d);
size_t avb=(a+b)/2;
sum+=num[a]*a-x[a];
sum+=X[b]-NUM[b]*b;
sum+=(NUM[avb]-NUM[b])*b-X[avb]+X[b];
sum+=x[avb]-x[a]-(num[avb]-num[a])*a;
cout<<sum<<endl;
}
}