[LOJ 6435] [PKUSC 2018] Interstellar

[LOJ 6435] [PKUSC 2018] Interstellar

The meaning of problems

Given \ (n-\) points, with each point \ ([l_i, i-1 ] \) point between the establishment of a bi-directional unit from the side. \ (Q \) group query from \ (X \) go \ ([l, r] \ ) random desired distance point output irreducible fraction.

\(n,q\le 3\times 10^5\), \(l<r<x\).

answer

Obvious to a \ (K \) , \ (K \) point in the steps to reach the \ ([1, x) \ ) a suffix. So that \ ([1, x) \ ) of point answer is divided into several segments, each segment identical answer and forward incremental.

Manually simulate what we can come to find that the first step in the left point is \ (L_x \) , the second step may come is \ (\ min \ limits_ {k \ ge l_x} l_k \) the reason is all step may reach \ (\ min \ limits_ {k \ ge l_x} l_k \) point can be necessarily \ (X \) step to reach (if \ (L_K \) in \ (k> x \) acquired at the minimum , then clearly \ (L_K <X \) . Also, because \ (K \) connection is \ ([L_K, K) \) , then the necessity and (X \) \ directly connected)., and the following step are shaped the \ (L_K \) suffix \ (\ min \) form.

So we can try to multiply in the second step and beyond.

While only doubling of the left edge point reached, while at the recording point from the sum of the multiplication skipped at the time. This may be (O (\ log n) \ ) \ calculated within the time \ (X \) to \ ( [l, x) \) at all points of the shortest and the two suffixes can be obtained and subtraction \ ([l, r] \ ) answers within.

Last minute about what output would be finished. Although the final answer is \ (O (n ^ 2) \) level but the data is not weak burst int...

Reference Code

#include <bits/stdc++.h>

const int MAXN=3e5+10;

int n;
int q;
int l[MAXN];
int lg[MAXN];
int sum[20][MAXN];
int prev[20][MAXN];
int* minl=prev[0];

int ReadInt();
int Calc(int,int);

int main(){
    n=ReadInt();
    for(int i=2;i<=n;i++)
        l[i]=ReadInt();
    q=ReadInt();
    l[1]=1;
    minl[n+1]=n;
    for(int i=n;i>=1;i--){
        minl[i]=std::min(l[i],minl[i+1]);
        sum[0][i]=i-minl[i];
    }
    for(int i=1;i<=n;i++)
        sum[0][i]=i-minl[i];
    for(int i=1;(1<<i)<=n;i++){
        lg[1<<i]=1;
        for(int j=1;j<=n;j++){
            prev[i][j]=prev[i-1][prev[i-1][j]];
            sum[i][j]=sum[i-1][j]+sum[i-1][prev[i-1][j]]+((prev[i-1][j]-prev[i][j])<<(i-1));
        }
    }
    for(int i=1;i<=n;i++)
        lg[i]+=lg[i-1];
    for(int i=0;i<q;i++){
        int l=ReadInt(),r=ReadInt(),pos=ReadInt();
        int a=Calc(pos,l)-Calc(pos,r+1);
        int b=r-l+1;
        int gcd=std::__gcd(a,b);
        printf("%d/%d\n",a/gcd,b/gcd);
    }
    return 0;
}

int Calc(int pos,int lim){
    if(l[pos]<lim)
        return pos-lim;
    int dis=0,p=l[pos],ans=pos-lim;
//  printf("x %d %d\n",ans,p);
    for(int i=lg[p];i>=0;i--){
        if(lim<=prev[i][p]){
            ans+=sum[i][p]+(p-prev[i][p])*dis;
//          printf("$ %d Q(%d,%d) %d\n",i,pos,lim,ans);
            p=prev[i][p];
            dis|=(1<<i);
        }
    }
    return ans+(p-lim)*(dis+1);
}

inline int ReadInt(){
    int x=0;
    register char ch=getchar();
    while(!isdigit(ch))
        ch=getchar();
    while(isdigit(ch)){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x;
}

Guess you like

Origin www.cnblogs.com/rvalue/p/10935041.html