概述
「PKUSC2018」星际穿越
Tags: 倍增 DP
「PKUSC2018」星际穿越
题意
不好概括就不概括啦qwq?
分析
考虑离线,把所有询问挂在x上。
然后对于当前的x,往左边所有的值一定是连续递增的。
然后又想到考场上yy的一个玄妙的主席树写法…不过实在是很玄妙现在也写不出来…?
然后是一个考场上想出来的东西
最多往右走一次
然后首先就是因为一开始打的暴力就不是标准的暴力所以完全没往倍增上想…反而满脑子都是主席树(虽然我jio得可以写)
首先是一个暴力。记f[x][i]为从x点走到i点的最小步数。这个处理是 n2 n 2 的,然而能拿到70pts。
然后考虑如何优化。对于上面的数组,下标是位置,存的是代价。然而可以想到代价一定是一条从x往左递减的序列。
这里考虑将下标和内容换过来,即
f[x][i]
f
[
x
]
[
i
]
表示的是从x出发向左走i步的最远左端点。
然后考虑做一个前缀和一样的东西,就可以求出
∑xi=ldis[x][i]
∑
i
=
l
x
d
i
s
[
x
]
[
i
]
之后用倍增优化一下就好了。
感觉说的乱七八糟的qwq 这个题解讲的讲的挺好的qwq
code
#include<bits/stdc++.h>
using namespace std;
#define M 300005
#define K 21
#define ll long long
void read(int &x){
x=0; char c=getchar();
for (;c<48;c=getchar());
for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48);
}
int f[M][K];
ll sum[M][K];
void Min(int &x,int y){
if (x>y)x=y;
}
int g[M],l[M],r[M],x[M];
ll cal(int x,int l){
if (g[x]<=l)return x-l;
ll res=x-g[x],base=1;
x=g[x];
int k;
for (k=K-1;k>=0;k--)if (f[x][k]>l){
res+=sum[x][k]+(x-f[x][k])*base;
x=f[x][k];
base+=(1<<k);
}
return res+(x-l)*(base+1);
}
int main(){
// freopen("1.in","r",stdin);
int n,m,i,L,k;
ll a,b,gcd;
read(n);
for (i=2;i<=n;i++){
read(g[i]);
}
read(m);
for (i=1;i<=m;i++){
read(l[i]); read(r[i]); read(x[i]);
}
L=n;
for (i=n;i>=1;i--){
Min(L,g[i]);
f[i][0]=L;
sum[i][0]=(i-L);
}
for (k=1;k<K;k++){
for (i=1;i<=n;i++)if (f[i][k-1]){
f[i][k]=f[f[i][k-1]][k-1];
sum[i][k]=sum[i][k-1]+sum[f[i][k-1]][k-1]+(f[i][k-1]-f[i][k])*(1ll<<(k-1));
}
}
for (i=1;i<=m;i++){
a=cal(x[i],l[i])-cal(x[i],r[i]+1);
b=r[i]-l[i]+1;
gcd=__gcd(a,b);
a/=gcd; b/=gcd;
printf("%lld/%lldn",a,b);
}
return 0;
}
最后
以上就是迷路店员为你收集整理的「PKUSC2018」星际穿越 [倍增]「PKUSC2018」星际穿越的全部内容,希望文章能够帮你解决「PKUSC2018」星际穿越 [倍增]「PKUSC2018」星际穿越所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复