我是靠谱客的博主 帅气世界,最近开发中收集的这篇文章主要介绍LOJ6435 PKUSC2018星际穿越ProblemSolutionCode,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Problem

loj

Solution

一个显而易见的结论,对于一个xi,要到达1号节点的最优路径只有第一步可能往右走,后面的步必定是往左走。
那么我们可以dp出整个右边可以走到的最左边的位置mn[i],mn[i]显然小于i,而且如果这个最优位置不是出自i本身,那么也就意味着要往右走一步,再往左走。
为什么mn[i]一定是最优的转移,难道不可能忽略一个中间可以到达的更优的进入情况吗?因为mn[i]也必定是从它dp出的mn[mn[i]],由于中间的点都必定已经经过被dp完了,所以是已经考虑过了的。
先dp出最优的位置,然后i就继承mn[i]的答案,做一个区间修改即可,可以用主席树实现操作,但是空间开销会稍微大一点。
有一个改进方法但是需要离线询问,注意到这个连边最后是一个树形结构,将询问按照dfs序来排序,然后对这棵树进行dfs回答询问。

Code

#include <algorithm>
#include <cstdio>
#define rg register
using namespace std;
const int maxn=300010,maxm=8000010,INF=0x3f3f3f3f;
int n,m,sz,l[maxn],mn[maxn],rt[maxn];
int lc[maxm],rc[maxm],add[maxm],sum[maxm];
template <typename Tp> inline void read(Tp &x)
{
    x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
void update(int l,int r,int L,int R,int val,int &rt)
{
    sz++;lc[sz]=lc[rt];rc[sz]=rc[rt];
    add[sz]=add[rt];sum[sz]=sum[rt];rt=sz;
    if(L<=l&&r<=R){add[rt]+=val;return ;}
    sum[rt]+=val*(min(r,R)-max(l,L)+1);
    int m=(l+r)>>1;
    if(L<=m) update(l,m,L,R,val,lc[rt]);
    if(m<R) update(m+1,r,L,R,val,rc[rt]);
}
int query(int l,int r,int L,int R,int rt)
{
    if(!rt) return 0;
    int res=add[rt]*(min(r,R)-max(l,L)+1);
    if(L<=l&&r<=R) return res+sum[rt];
    int m=(l+r)>>1;
    if(L<=m) res+=query(l,m,L,R,lc[rt]);
    if(m<R) res+=query(m+1,r,L,R,rc[rt]);
    return res;
}
void input()
{
    read(n);
    for(rg int i=2;i<=n;i++) read(l[i]);
    read(m);mn[n]=l[n];
    for(rg int i=n-1;i;i--)
      mn[i]=min(mn[i+1],l[i]);//整个右边可以到达的最左边的点,包括考虑了往右边走一步
    for(rg int i=2;i<=n;i++)
    {
        rt[i]=rt[mn[i]];
        update(1,n,1,i-1,1,rt[i]);//这里可能少考虑了往右走再跳回来的贡献
    }//但是没关系,在后来处理的时候初始化权值时即可
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    int ql,qr,x,len,ans,d;
    input();
    for(rg int i=1;i<=m;i++)
    {
        read(ql);read(qr);read(x);
        ans=len=qr-ql+1;
        if(ql<l[x]) ans+=query(1,n,ql,min(qr,l[x]-1),rt[l[x]]);
        d=gcd(ans,len);
        printf("%d/%dn",ans/d,len/d);
    }
    return 0;
}

最后

以上就是帅气世界为你收集整理的LOJ6435 PKUSC2018星际穿越ProblemSolutionCode的全部内容,希望文章能够帮你解决LOJ6435 PKUSC2018星际穿越ProblemSolutionCode所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部