欢迎来到蒟蒻mqd的博客

H - The LCIS on the Tree HDU - 4718

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("\n");
133   printf("Case #%d:\n",++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\n",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

 

posted @ 2019-04-29 23:52  mmqqdd  阅读(238)  评论(0编辑  收藏  举报