【JZOJ5246】【NOIP2017模拟8.8A组】Trip

来源:互联网 发布:盛世传奇翅膀进阶数据 编辑:程序博客网 时间:2024/06/08 17:41

Description

多年之后,worldwideD厌倦竞争,隐居山林。
他的家乡开始发展起了旅游业,在一条很长的主干道上,有N个旅游景点,按顺序编号为1到N。根据游客们网上的评分,第i个景点有一个评估值a[i],为了区分开不同的景点,评估值是两两不同的。
今天有M组游客前来旅游,第i组游客选择遍历景点Li到景点Ri这一段路。他们搜到Li到Ri的所有评估值,如果对于景点j(Li≤j≤Ri),不存在景点x(Li≤x<j)满足a[x]>a[j]或不存在景点y(j<y≤Ri)满足a[y]>a[j],那么他们会进入景点j。
现在worldwideD想知道,每组游客会去多少个景点。

Data Constraint

30%:N,M≤5,000
60%:N,M≤100,000
100%:N,M≤1,000,000 0≤|a[i]|≤1,000,000,000 1≤Li≤Ri≤N

Solution

我们勾出一颗笛卡尔树,我们发现从l到lca的路径上唯有左子树到父亲是有贡献的,r到lca上唯有右子树到父亲是有贡献的。(因为l到lca的路径上若为右子树,说明l在父亲右边,不合法)
所以对于询问,直接用tarjan求一个lca即可。时间复杂度O(N)。

Code

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;const int maxn=1e6+5;struct code{    int x,y,lca;}b[maxn];int a[maxn],d[maxn],f[maxn][2],first[maxn],last[2*maxn],next[2*maxn],fa[maxn];int id[maxn*2],bz[maxn],l[maxn],r[maxn];int n,m,i,mx,ans,t,j,k,x,y,z,num;char ch;void lian(int x,int y,int z){    last[++num]=y;next[num]=first[x];first[x]=num;id[num]=i;}int getfa(int x){    return (fa[x]==x)?x:fa[x]=getfa(fa[x]);}void dg(int x,int y){    int t;    if (!x) return;    l[f[x][0]]=l[x]+1;l[f[x][1]]=l[x];    r[f[x][1]]=r[x]+1;r[f[x][0]]=r[x];    dg(f[x][0],x);dg(f[x][1],x);    for (t=first[x];t;t=next[t])        if (bz[last[t]]){            z=getfa(last[t]);            b[id[t]].lca=z;        }    bz[x]=1;    fa[x]=y;}int read(){       int x=0,sig=1;       char c;       for (c=getchar();c<'0' || c>'9';c=getchar()) if (c=='-') sig=-1;       for (;c>='0' && c<='9';c=getchar()) x=x*10+c-48;       return x*sig;}int main(){    freopen("trip.in","r",stdin);freopen("trip.out","w",stdout);    scanf("%d%d\n",&n,&m);    for (i=1;i<=n;i++){        a[i]=read();        while (a[d[d[0]]]<a[i] && d[0]) d[0]--;        f[i][0]=f[d[d[0]]][1];fa[i]=i;        f[d[d[0]]][1]=i;        d[++d[0]]=i;    }    scanf("\n");    for (i=1;i<=m;i++){        x=read();y=read();        b[i].x=x,b[i].y=y;        if (b[i].x==b[i].y) b[i].lca=x;        else lian(x,y,i),lian(y,x,i);    }    dg(d[1],0);    for (i=1;i<=m;i++){        t=l[b[i].x]-l[b[i].lca]+r[b[i].y]-r[b[i].lca]+1;        printf("%d\n",t);    }}
原创粉丝点击