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.
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.
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.
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 }