「PKUSC2018」星际穿越 [倍增]

「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/%lld\n",a,b);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值