zoukankan      html  css  js  c++  java
  • H

    The LCIS on the Tree

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
    Total Submission(s): 1615    Accepted Submission(s): 457


    题目链接

    https://vjudge.net/problem/UVA-12655

     

    Problem Description

    For a sequence S1, S2, ... , SN, and a pair of integers (i, j), if 1 <= i <= j <= N and Si < Si+1 < Si+2 < ... < Sj-1 < Sj , then the sequence Si, Si+1, ... , Sj is a CIS (Continuous Increasing Subsequence). The longest CIS of a sequence is called the LCIS (Longest Continuous Increasing Subsequence).
    Now we consider a tree rooted at node 1. Nodes have values. We have Q queries, each with two nodes u and v. You have to find the shortest path from u to v. And write down each nodes' value on the path, from u to v, inclusive. Then you will get a sequence, and please show us the length of its LCIS.
     

    Input

    The first line has a number T (T <= 10) , indicating the number of test cases.
    For each test case, the first line is a number N (N <= 105), the number of nodes in the tree.
    The second line comes with N numbers v1, v2, v3 ... , vN, describing the value of node 1 to node N. (1 <= vi <= 109)
    The third line comes with N - 1 numbers p2, p3, p4 ... , pN, describing the father nodes of node 2 to node N. Node 1 is the root and will have no father.
    Then comes a number Q, it is the number of queries. (Q <= 105)
    For next Q lines, each with two numbers u and v. As described above.
     

    Output

    For test case X, output "Case #X:" at the first line.
    Then output Q lines, each with an answer to the query.
    There should be a blank line *BETWEEN* each test case.
     

    Sample Input

    1 5 1 2 3 4 5 1 1 3 3 3 1 5 4 5 2 5
     

    Sample Output

    Case #1: 3 2 3

    题意

    在一棵树上,每次求一条路径最长连续上升子序列。

    题解

    一开始看错题,以为求最长上升子序列,然后想了好久毫无思路,一看题解发现原来我看错题了。

    连续的话就不难了。

    树链剖分,然后线段树记录一下该区间最长上升子序列,左端点开始的最长上升子序列长度,右端点。。。

    反正就是考虑如果知道左子树和右子树的信息,如何合并。显然合并就是中间可能延长,其他的都一样。

    但是在树上,x-->lca(x,y) 和 lca(x,y)-->是不一样的,x-->lca(x,y)需要求最长下降子序列,然后就是一对细节需要处理,具体看代码吧。

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define ll long long
      4 #define N 500050
      5 struct Tree{int l,r,lb,rb,lI,rI,lD,rD,Imx,Dmx;}tr[N<<2];
      6 struct Edge{int from,to,s;}edges[N<<1];
      7 int n,m,cas,w[N];
      8 int tot,last[N];
      9 int cnt,fa[N],dp[N],size[N],son[N],rk[N],kth[N],top[N];
     10 template<typename T>void read(T&x)
     11 {
     12   ll k=0; char c=getchar();
     13   x=0;
     14   while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
     15   if (c==EOF)exit(0);
     16   while(isdigit(c))x=x*10+c-'0',c=getchar();
     17   x=k?-x:x;
     18 }
     19 void read_char(char &c)
     20 {while(!isalpha(c=getchar())&&c!=EOF);}
     21 void AddEdge(int x,int y)
     22 {
     23   edges[++tot]=Edge{x,y,last[x]};
     24   last[x]=tot;
     25 }
     26 void dfs1(int x,int pre)
     27 {
     28   fa[x]=pre;
     29   dp[x]=dp[pre]+1;
     30   size[x]=1;
     31   son[x]=0;
     32   for(int i=last[x];i;i=edges[i].s)
     33     {
     34       Edge &e=edges[i];
     35       if (e.to==pre)continue;
     36       dfs1(e.to,x);
     37       size[x]+=size[e.to];
     38       if(size[e.to]>size[son[x]])son[x]=e.to;
     39     }
     40 }
     41 void dfs2(int x,int y)
     42 {
     43   rk[x]=++cnt;
     44   kth[cnt]=x;
     45   top[x]=y;
     46   if (son[x]==0)return;
     47   dfs2(son[x],y);
     48   for(int i=last[x];i;i=edges[i].s)
     49     {
     50       Edge &e=edges[i];
     51       if (e.to==fa[x]||e.to==son[x])continue;
     52       dfs2(e.to,e.to);
     53     }
     54 }
     55 void init(Tree &a){a=Tree{0,0,0,0,0,0,0,0,0,0};}
     56 template<typename T>void he(T &c,T a, T b)
     57 {
     58   if (a.Imx==0){c=b;return;}
     59   if (b.Imx==0){c=a;return;}
     60   c.l=a.l; c.r=b.r;
     61   int lena=a.r-a.l+1,lenb=b.r-b.l+1;
     62   c.lb=a.lb; c.rb=b.rb;
     63   c.lI=lena==a.lI&&a.rb<b.lb?lena+b.lI:a.lI;
     64   c.lD=lena==a.lD&&a.rb>b.lb?lena+b.lD:a.lD;
     65   c.rI=lenb==b.rI&&a.rb<b.lb?lenb+a.rI:b.rI;
     66   c.rD=lenb==b.rD&&a.rb>b.lb?lenb+a.rD:b.rD;
     67   c.Imx=max(a.Imx,b.Imx);
     68   c.Imx=max(c.Imx,a.rb<b.lb?a.rI+b.lI:0);
     69   c.Dmx=max(a.Dmx,b.Dmx);
     70   c.Dmx=max(c.Dmx,a.rb>b.lb?a.rD+b.lD:0);
     71 }
     72 void bt(int x,int l,int r)
     73 {
     74   tr[x].l=l; tr[x].r=r;
     75   if (l==r)
     76     {
     77       tr[x]={l,r,w[kth[l]],w[kth[l]],1,1,1,1,1,1};
     78       return;
     79     }
     80   int mid=(l+r)>>1;
     81   bt(x<<1,l,mid);
     82   bt(x<<1|1,mid+1,r);
     83   he(tr[x],tr[x<<1],tr[x<<1|1]);
     84 }
     85 Tree query(int x,int l,int r)
     86 {
     87   if (l<=tr[x].l&&tr[x].r<=r)
     88     return tr[x];
     89   int mid=(tr[x].l+tr[x].r)>>1;
     90   Tree tp1,tp2,tp; init(tp1); init(tp2);
     91   if (l<=mid)tp1=query(x<<1,l,r);
     92   if (mid<r)tp2=query(x<<1|1,l,r);
     93   he(tp,tp1,tp2);
     94   return tp;
     95 }
     96 int get_max(int x,int y)
     97 {
     98   int fx=top[x],fy=top[y],ans=0;
     99   Tree tpx,tpy,tp;
    100   init(tpx); init(tpy);
    101   while(fx!=fy)
    102     {
    103       if (dp[fx]>dp[fy])
    104     {
    105       tp=query(1,rk[fx],rk[x]);
    106       he(tpx,tp,tpx);
    107       x=fa[fx]; fx=top[x];
    108     }
    109       else
    110     {
    111       tp=query(1,rk[fy],rk[y]);
    112       he(tpy,tp,tpy);
    113       y=fa[fy]; fy=top[y];
    114     }
    115     }
    116   if (dp[x]>dp[y])
    117     {
    118       tp=query(1,rk[y],rk[x]);
    119       he(tpx,tp,tpx);
    120     }
    121   else
    122     {
    123       tp=query(1,rk[x],rk[y]);
    124       he(tpy,tp,tpy);
    125     }
    126   ans=max(tpx.Dmx,tpy.Imx);
    127   ans=max(ans,tpx.lb<tpy.lb?tpx.lD+tpy.lI:0);
    128   return ans;
    129 }
    130 void work()
    131 {
    132   if (cas)printf("
    ");
    133   printf("Case #%d:
    ",++cas);
    134   read(n);
    135   for(int i=1;i<=n;i++)read(w[i]);
    136   for(int i=2;i<=n;i++)
    137     {
    138       int x;
    139       read(x);
    140       AddEdge(x,i);
    141     }
    142   dfs1(1,0);
    143   dfs2(1,1);
    144   bt(1,1,n);
    145   read(m);
    146   for(int i=1;i<=m;i++)
    147     {
    148       int x,y;
    149       read(x); read(y);
    150       printf("%d
    ",get_max(x,y));
    151     }
    152 }
    153 void clear()
    154 {
    155   cnt=0; tot=0;
    156   memset(last,0,sizeof(last));
    157 }
    158 int main()
    159 {
    160 #ifndef ONLINE_JUDGE
    161   freopen("aa.in","r",stdin);
    162 #endif
    163   int q;
    164   read(q);
    165   while(q--)
    166     {
    167       clear();
    168       work();
    169     } 
    170 }
    View Code
  • 相关阅读:
    python操作MongoDB
    MongoDB操作——备忘录
    python中运行js代码—js2py
    糗事百科爬虫_基于线程池
    糗事百科_基于队列和多线程
    Django ModelForm组件
    Django补充(mark_safe,url反向解析)
    Django MiddleWare中间件
    Python常用模块 -- sys模块的常用用法
    Python常用模块 -- os模块常用用法
  • 原文地址:https://www.cnblogs.com/mmmqqdd/p/10793607.html
Copyright © 2011-2022 走看看