【NOIP2017模拟8.8A组】Trip(trip)

来源:互联网 发布:bing词典mac 编辑:程序博客网 时间:2024/06/05 15:30

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想知道,每组游客会去多少个景点。

Input

第一行两个整数N,M,意义见题面。
接下来一行N个整数,第i个是a[i],意义见题面。
接下来M行,第i行两个整数Li,Ri,意义见题目。

Output

M行,第i行表示第i组游客去的景点个数。

Sample Input

6 4
3 1 7 4 5 2
1 5
2 5
2 6
4 6

Sample Output

3
3
4
3

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

题解

先考虑按照a的值构造一棵笛卡尔树,对于一个询问l,r答案就是他们的lca到他们这两条链中到l链的每一个父亲的左儿子个数以及到r那边的右儿子个数
为什么这样做是对的呢?事实上对答案有贡献的并不是那个树节点对应的序列中的位置,如果这个点在序列中的位置在[l,r]外,那么一定有另一个在[l,r]中的点可以满足题目的要求
那么我们可以tarjan求lca,单调栈构造笛卡尔树来O(n)解决这个问题

贴代码

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=1000005;int a[maxn],fi[2*maxn],next[2*maxn],dui[2*maxn],sc[2*maxn],st[maxn*2],hc[maxn*2];int fa[maxn],da[maxn],son[maxn][3],zu[maxn],yo[maxn];int go[maxn][4];bool bz[maxn];int i,j,k,l,n,m,x,y,ans,p,root;bool b1;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;}void write(int x){    if (!x) putchar('0');else    {        char s[10];        int i,j=0;        for (;x>0;x/=10) s[j++]=x%10;        for (i=j-1;i>=0;i--) putchar(s[i]+48);    }    putchar('\n');}void add(int x,int y){    if (!fi[x]){        fi[x]=++l; dui[l]=y; sc[x]=l;    } else{        next[sc[x]]=++l; dui[l]=y; sc[x]=l;    }    hc[l]=i;}int getfather(int x){    if (fa[x]==x) return x; else fa[x]=getfather(fa[x]);    return fa[x];}void dfs(int x){    fa[x]=x;    bz[x]=true;    p=fi[x];    if (da[x]>0){        zu[x]=zu[da[x]]; yo[x]=yo[da[x]];        if (son[da[x]][1]==x) zu[x]++; else yo[x]++;    }    while (p){        if (bz[dui[p]]==true) go[hc[p]][3]=getfather(dui[p]);        p=next[p];    }    if (son[x][1]) dfs(son[x][1]);    if (son[x][2]) dfs(son[x][2]);    fa[x]=da[x];}int main(){//  freopen("t3.in","r",stdin);    freopen("trip.in","r",stdin);    freopen("trip.out","w",stdout);    scanf("%d%d",&n,&m);    fo(i,1,n) a[i]=read();    fo(i,1,m)    {        go[i][1]=read(); go[i][2]=read();        add(go[i][1],go[i][2]);        add(go[i][2],go[i][1]);    }    l=0;    fo(i,1,n){        b1=false;        while (l>0 && a[i]>a[st[l]])         {            l--;            b1=true;        }        if (b1){            da[i]=da[st[l+1]];            da[st[l+1]]=da[i];            son[da[i]][2]=i;            son[i][1]=st[l+1];            da[st[l+1]]=i;        } else {            son[st[l]][2]=i;            da[i]=st[l];        }        st[++l]=i;        if (l==1) root=i;    }    dfs(root);    fo(i,1,m){        ans=-zu[go[i][3]]+zu[go[i][1]]-yo[go[i][3]]+yo[go[i][2]]+1;        write(ans);    }    return 0;}
原创粉丝点击