欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JZOJ5865. 【NOIP2018模拟9.11】假期旅行

程序员文章站 2022-03-31 08:07:50
...

JZOJ5865. 【NOIP2018模拟9.11】假期旅行
JZOJ5865. 【NOIP2018模拟9.11】假期旅行

题解

ai表示从i这个位置出发,只用一个座位,最远可以到达的地方。
这个可以用线段树求出来。
考虑倍增,
fi,j表示从i出发,换2j次座位,最远到达的位置,
这个就跟普通的倍增没有区别,
然后求答案也是倍增。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#define N 200003
#define db double
#define P putchar
#define G getchar
#define ls (x<<1)
#define rs (x<<1|1)
#define M ((l+r)>>1)
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    int w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int max(int x,int y){return x>y?x:y;}
void write(int x){if(x>9) write(x/10);P(x%10+'0');}

struct node
{
    int l,r,a;
}a[N];

int n,m,k,st,fi,q,cnt,op,lst,mr,ans;
int f[23][N],z[23];
int opl,opr,ops,mx[N*4],lazy[N*4];

bool cmp1(node a,node b)
{
    return a.a<b.a || (a.a==b.a && a.l<b.l) || (a.a==b.a && a.l==b.l && a.r<b.r);
}

void down(int x)
{
    if(!lazy[x])return;
    mx[ls]=max(mx[ls],lazy[x]);
    mx[rs]=max(mx[rs],lazy[x]);
    lazy[ls]=max(lazy[x],lazy[ls]);
    lazy[rs]=max(lazy[x],lazy[rs]);
}

int find(int x,int l,int r)
{
    if(l==r)return mx[x];
    down(x);
    int m=M;
    return (opl<=m)?find(ls,l,m):find(rs,m+1,r);
}

void work(int x,int l,int r)
{
    if(opl<=l && r<=opr)
    {
        lazy[x]=max(lazy[x],ops);
        mx[x]=max(mx[x],ops);
        return;
    }
    down(x);
    int m=M;
    if(opl<=m)work(ls,l,m);
    if(m<opr)work(rs,m+1,r);
    mx[x]=max(mx[ls],mx[rs]);
}

int main()
{
    freopen("trip.in","r",stdin);
    freopen("trip.out","w",stdout);

    read(n);read(m);read(k);
    for(int i=1;i<=m;i++)
        read(a[i].l),read(a[i].r),read(a[i].a);
    sort(a+1,a+m+1,cmp1);op=1;

    for(int i=1;i<=k;i++)
    {
        lst=1;
        for(;a[op].a==i;op++)
        {
            if(lst<a[op].l)
            {
                opl=lst,opr=a[op].l-1;ops=a[op].l;
                if(opl<=opr)work(1,1,n);
            }

            mr=a[op].r;
            for(;a[op+1].l<=mr && a[op+1].a==i;op++)mr=max(mr,a[op+1].r);
            lst=mr;
        }

        if(lst<n)opl=lst,opr=ops=n,work(1,1,n);
    }

    for(int i=1;i<n;i++)
    {
        opl=i,f[0][i]=find(1,1,n);
        if(!f[0][i])f[0][i]=n+1;
    }

    z[0]=1;f[0][n]=n;f[0][n+1]=n+1;
    for(int j=1;j<20;j++)
    {
        z[j]=z[j-1]<<1;
        for(int i=1;i<=n+1;i++)
            f[j][i]=f[j-1][f[j-1][i]];
    }

    /*for(int i=1;i<=n;i++)
        printf("%d\n",f[0][i]);*/

    for(read(q);q;q--)
    {
        read(st);read(fi);

        ans=0;
        for(int j=19;j>=0;j--)
            if(f[j][st]<fi)
            {
                st=f[j][st];
                ans=ans+z[j];
            }
        ans++;st=f[0][st];

        if(st>n || st<fi)P('-'),P('1');
            else write(ans);
        P('\n');
    }

    return 0;
}