倍增从入门到入土
入门
P1081 [NOIP2012 提高组] 开车旅行
tj前:看到第一第二大,可以倍增维护,但是这建边也太恶心了,然后对于第一问我在挨个点跑一边?倍增起码有个区间吧,宁给我个 \(x_0\) 我也不知道该从那么跑哇,只能从头往后排,这不曼斯?
比值可以模拟,但是这该怎么跑
tj后:看了看可以模拟,我先试试
70分暴力模拟
/*
c1[i] 距离i最近的城市
c2[i] 距离i次进的城市
dis1[i] 从i到c[i]的距离
dis2[i] 同理 次二进的
A---2
B---1+
*/
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <bits/stdc++.h>
#include <algorithm>
#define int long long
using namespace std;
const int A = 1e7+10;
const int B = 1e6+10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int n,m,h[B],xl,p;
int dis1[B],dis2[B],c1[B],c2[B];
double minv=INT_MAX;
main()
{
int x,y;
n=read();
for (int i=1;i<=n;i++) h[i]=read();
for (int i=n-1;i>=1;i--)
{
int minx=i+1,minxx=0;
dis1[i]=abs(h[i]-h[i+1]);
for (int j=i+2;j<=n;j++)
{
if (dis1[i]>abs(h[i]-h[j]) || (dis1[i]==abs(h[i]-h[j]) && h[j]<h[minx]))
{
minxx=minx;
minx=j;
dis2[i]=dis1[i];
dis1[i]=abs(h[i]-h[j]);
}
else if (dis2[i]==0 || dis2[i]>abs(h[i]-h[j]) || (dis2[i]==abs(h[i]-h[j]) && h[j]<h[minxx]))
{
minxx=j;
dis2[i]=abs(h[i]-h[j]);
}
}
c1[i]=minx;
c2[i]=minxx;
}
xl=read();
int ans=0;
for (int i=1;i<=n;i++)
{
int js=0,sum=0,a=0,b=0;
int s=i;
while (1)
{
if(!js)
{
if (a+b+dis2[s]>xl || !c2[s]) break;
a+=dis2[s];
s=c2[s];
}
else
{
if (a+b+dis1[s]>xl || !c1[s]) break;
b+=dis1[s];
s=c1[s];
}
js^=1;
}
if (!ans || 1.0*a / b - minv < -0.00000001 || (fabs(1.0*a / b - minv) <= 0.00000001&&h[ans] < h[i]))
{
minv = 1.0*a / b;
ans = i;
}
}
printf("%lld\n",ans);
p=read();
while (p--)
{
int w,js=0,a=0,b=0;
x=read(),y=read();
int s=x;
while (1)
{
if(!js)
{
if (a+b+dis2[s]>y || !c2[s]) break;
a+=dis2[s];
s=c2[s];
}
else
{
if (a+b+dis1[s]>y || !c1[s]) break;
b+=dis1[s];
s=c1[s];
}
js^=1;
}
printf("%lld %lld\n",a,b);
}
return 0;
}
倍增优化,双向链表初始化
做完我都在想今天晚上我为甚选择的宁,一晚上没了
/*
c1[i] 距离i最近的城市
c2[i] 距离i次进的城市
dis1[i] 从i到c[i]的距离
dis2[i] 同理 次二进的
A---2
B---1+
*/
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <bits/stdc++.h>
#include <algorithm>
#define int long long
using namespace std;
const int A = 1e7+10;
const int B = 1e6+10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int n,m,h[B],xl,p;
int pos[B],dis1[B],dis2[B],c1[B],c2[B];
int c3[B][21],dist3[B][21], dist4[B][21], dist5[B][21];
double minv=INT_MAX;
struct node{int h,bh,last,next;}q[B];
bool cmp(node a,node b){return a.h<b.h;}
void updata(int i,int loc,int x)
{
if (x>=1 && x<=n)
{
if (!dis1[i] || dis1[i]>abs(q[loc].h -q[x].h) || (dis1[i]==abs(q[loc].h -q[x].h) && q[x].h <q[pos[c1[i]]].h))
{
c2[i]=c1[i];
c1[i]=q[x].bh;
dis2[i]=dis1[i];
dis1[i]=abs(q[loc].h -q[x].h);
}
else if (dis2[i]==0 || dis2[i]>abs(q[loc].h -q[x].h) || (dis2[i]==abs(q[loc].h -q[x].h) && q[x].h <q[pos[c2[i]]].h))
{
c2[i]=q[x].bh;
dis2[i]=abs(q[loc].h -q[x].h);
}
}
}
main()
{
int x,y;
n=read();
for (int i=1;i<=n;i++) q[i].h=read(),q[i].bh=i;
sort(q+1,q+1+n,cmp);
for (int i=1;i<=n;i++)
{
pos[q[i].bh]=i;
if (i!=1) q[i].last=i-1;
if (i!=n) q[i].next=i+1;
}
for (int i=1;i<=n;i++)
{
int loc = pos[i];
updata(i, loc, q[q[loc].last].last);
updata(i, loc, q[loc].last);
updata(i, loc, q[loc].next);
updata(i, loc, q[q[loc].next].next);
if (q[loc].last)q[q[loc].last].next = q[loc].next;
if (q[loc].next)q[q[loc].next].last = q[loc].last;
q[loc].last = q[loc].next = 0;
}
for ( int i = 1; i <= n; ++i)
{
dist4[i][0] = dis2[i];
dist5[i][0] = dis1[c2[i]];
dist3[i][0] = dis2[i] + dis1[c2[i]];
c3[i][0] = c1[c2[i]];
}
for ( int j = 1; j <= 20; ++j)
for ( int i = 1; i <= n; ++i)
{
c3[i][j] = c3[c3[i][j - 1]][j - 1];
if (c3[i][j])
{
dist3[i][j] = dist3[i][j - 1] + dist3[c3[i][j - 1]][j - 1];
dist4[i][j] = dist4[i][j - 1] + dist4[c3[i][j - 1]][j - 1];
dist5[i][j] = dist5[i][j - 1] + dist5[c3[i][j - 1]][j - 1];
}
}
int xx = read(), ans = 0;
for (int i = 1; i <= n; ++i)
{
int a = 0, b = 0, loc = i, x0 = xx;
for ( int j = 20; j >= 0; --j)
{
if (dist3[loc][j] && x0 >= dist3[loc][j])
{
x0 -= dist3[loc][j];
a += dist4[loc][j];
b += dist5[loc][j];
loc = c3[loc][j];
}
}
if (dis2[loc] <= x0)a += dis2[loc];
if (a <= 0)continue;
if (!ans || 1.0*a / b - minv < -0.00000001 || (fabs(1.0*a / b - minv) <= 0.00000001&&q[pos[ans]].h < q[pos[i]].h))
{
minv = 1.0*a / b;
ans = i;
}
}
printf("%lld\n",ans);
p=read();
while (p--)
{
int s = read(), x = read(), a = 0, b = 0;
for ( int j = 20; j >= 0; --j)
{
if (dist3[s][j] && x >= dist3[s][j])
{
x -= dist3[s][j];
a += dist4[s][j];
b += dist5[s][j];
s = c3[s][j];
}
}
if (dis2[s] <= x)a += dis2[s];
printf("%lld %lld\n", a, b);
}
return 0;
}