md這sb題怎麼這麼墨跡,在心裏默默地罵出題人
咳咳
題目大意:
在一個數軸上,每個點有互不相同的點權,規定兩點之間距離爲兩個的點權的差的絕對值,現在從最左面出發,只能向右走,交替的走次大值和最大值,然後現在問在規定的距離內,兩個人向右走,兩個人分別能走多少路
思博倍增,普及組小孩都會
首先,暴力的話可以直接預處理出下一個點能走的最大值和次大值都是誰,然後暴力的走下去。
然後我們發現這個東西可以倍增,我們先維護出一個點能向右走的最大值和次大值,然後我們就可以玩了
用
然後直接倍增,在倍增處理位置的同時維護一下分別走的距離,然後玩一下就行了。
在維護最大值次大值的時候可以用
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <cmath>
const int N = 100000+5;
typedef long long LL;
LL inf = 1e15;
using namespace std;
struct cmps
{
int val,now,pos;
cmps () {}
cmps (LL _val,int _now,int _pos):val(_val),now(_now),pos(_pos){}
bool operator < (const cmps &z)const
{
return now ^ z.now ? now < z.now : val < z.val;
}
}tmp[5];
struct Lux
{
int pos;
int val;
bool operator < (const Lux & z)const
{
return val ^ z.val ? val < z.val : pos < z.pos;
}
}a[N];
int L[N];
int R[N];
int T[N];
inline int read()
{
int x=0,f=1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')f=-1;ch = getchar();}
while(ch >='0' && ch <='9'){x=(x<<1)+(x<<3)+ch-'0';ch = getchar();}
return x*f;
}
int next_Fir[N];
int next_Sec[N];
int next[N][20];
LL dis[N][20];
LL disA[N][20];
LL H[N];
bool equal(double A,double B)
{
return fabs(A-B) < (1e-9)*max(A,B);
}
double calc(double A,double B)
{
if(equal(B,0))
return 1e9;
else return A / B;
}
int main()
{
// freopen("27.in", "r", stdin);
int n = read();
for(int i=1;i<=n;++i) a[i].pos = i ,H[i] = a[i].val = read();
sort(a+1,a+n+1);
for(int i=1;i<=n;++i)
{
L[i] = i - 1;
R[i] = i + 1;
T[a[i].pos] = i;
}
H[0] = H[n+1] = inf;
for(int t=1;t<=n;++t)
{
int tot = 0;
int i = T[t];
if(L[i]) tmp[++tot] = cmps(a[L[i]].val,labs(a[i].val - a[L[i]].val),a[L[i]].pos);
if(L[L[i]]) tmp[++tot] = cmps(a[L[L[i]]].val,labs(a[i].val - a[L[L[i]]].val),a[L[L[i]]].pos);
if(R[i] <= n) tmp[++tot] = cmps(a[R[i]].val,labs(-a[i].val + a[R[i]].val),a[R[i]].pos);
if(R[R[i]] <= n) tmp[++tot] = cmps(a[R[R[i]]].val,labs(-a[i].val + a[R[R[i]]].val),a[R[R[i]]].pos);
if(tot == 0)continue;
if(tot == 1){next_Fir[a[i].pos] = tmp[1].pos;L[R[i]] = L[i];R[L[i]] = R[i];continue;}
sort(tmp+1,tmp+tot+1);
next_Fir[a[i].pos] = tmp[1].pos;
next_Sec[a[i].pos] = tmp[2].pos;
L[R[i]] = L[i];
R[L[i]] = R[i];
}
for(int i=1;i<=n;++i)
{
next[i][0] = next_Sec[i];
next[i][1] = next_Fir[next[i][0]];
dis[i][0] = labs(H[next[i][0]] - H[i]);
dis[i][1] = dis[i][0] + labs(H[next[i][1]] - H[next[i][0]]);
disA[i][0] = disA[i][1] = dis[i][0];
}
for(int j=2;j<=18;++j)
for(int i=1;i<=n;++i)
{
next[i][j] = next[next[i][j-1]][j-1];
dis[i][j] = dis[next[i][j-1]][j-1] + dis[i][j-1];
disA[i][j] = disA[next[i][j-1]][j-1] + disA[i][j-1];
}
for(int j=0;j<=18;++j)
for(int i=1;i<=n;++i)
if(!next[i][j])
next[i][j] = n + 1,dis[i][j] = 1e9+5;
LL lmt = read();
int pos = 0;
double ans = 1e16;
for(int i=1;i<=n;++i){
LL tmp = 0;
int x = i;
LL tlmt = lmt;
LL all = 0;
for(int j=18;j>=0 && x!=n+1;--j)
if(lmt >= dis[x][j])
{
lmt -= dis[x][j];
tmp += disA[x][j] ;
all += dis[x][j];
x = next[x][j];
}
LL tmpB = all - tmp;
LL tmpA = tmp;
double tt = calc(tmpA,tmpB);
// printf("%.2lf\n",tt);
if(equal(tt,ans))
{
if(H[pos] < H[i])
pos = i;
}
else if(tt < ans)
{
ans = tt;
pos = i;
}
lmt = tlmt;
}
cout << pos << endl;
int m = read();
while(m--){
LL tmp = 0;
int x = read();
lmt = read();
LL all = 0;
for(int j=18;j>=0 && x!=n+1;--j){
if(lmt >= dis[x][j])
{
lmt -= dis[x][j];
all += dis[x][j];
tmp += disA[x][j];
x = next[x][j];
}
// cout << x << " " << tmp << endl;
}
LL tmpB = all - tmp;
LL tmpA = tmp;
printf("%lld %lld\n",tmpA,tmpB);
}
}