The LCIS on the Tree HDU - 4718

2024-02-22 18:48
文章标签 tree hdu 4718 lcis

本文主要是介绍The LCIS on the Tree HDU - 4718,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://acm.hdu.edu.cn/showproblem.php?pid=4718

链上LCIS 用区间合并解决 线段树每次查询都带回该区间内的左值 右值 左连续段 右连续段 最大连续段 然后和该链上的上一次查询合并 这里直接当做线段树区间合并的法子写的 uv两点顺着两条链向上爬 会师后特殊处理即可

7000+的代码 debug一天。。 爬链时开了很多没用的变量 反正多了没错。。

#include <bits/stdc++.h>
using namespace std;
#define N 0x3f3f3f3fstruct node1
{int v;int next;
};struct node2//0 up   1 down
{int l;int r;int lval;int rval;int left0;int right0;int all0;int left1;int right1;int all1;
};node1 edge[200010];
node2 tree[400010];
int val[100010],first[100010],fa[100010],deep[100010],sum[100010],son[100010],top[100010],mp1[100010],mp2[100010];
int n,q,num;void addedge(int u,int v)
{edge[num].v=v;edge[num].next=first[u];first[u]=num++;
}void dfsI(int cur)
{int i,v;sum[cur]=1,son[cur]=-1;for(i=first[cur];i!=-1;i=edge[i].next){v=edge[i].v;if(v!=fa[cur]){fa[v]=cur,deep[v]=deep[cur]+1;dfsI(v);sum[cur]+=sum[v];if(son[cur]==-1||sum[son[cur]]<sum[v]){son[cur]=v;}}}
}void dfsII(int cur,int tp)
{int i,v;num++;top[cur]=tp,mp1[cur]=num,mp2[num]=cur;if(son[cur]==-1) return;dfsII(son[cur],tp);for(i=first[cur];i!=-1;i=edge[i].next){v=edge[i].v;if(v!=fa[cur]&&v!=son[cur]){dfsII(v,v);}}
}void pushup(int cur)
{tree[cur].lval=tree[2*cur].lval,tree[cur].rval=tree[2*cur+1].rval;tree[cur].left0=tree[2*cur].left0;if(tree[cur].left0==tree[2*cur].r-tree[2*cur].l+1&&tree[2*cur].rval<tree[2*cur+1].lval) tree[cur].left0+=tree[2*cur+1].left0;tree[cur].right0=tree[2*cur+1].right0;if(tree[cur].right0==tree[2*cur+1].r-tree[2*cur+1].l+1&&tree[2*cur].rval<tree[2*cur+1].lval) tree[cur].right0+=tree[2*cur].right0;tree[cur].all0=max(tree[2*cur].all0,tree[2*cur+1].all0);if(tree[2*cur].rval<tree[2*cur+1].lval) tree[cur].all0=max(tree[cur].all0,tree[2*cur].right0+tree[2*cur+1].left0);tree[cur].left1=tree[2*cur].left1;if(tree[cur].left1==tree[2*cur].r-tree[2*cur].l+1&&tree[2*cur].rval>tree[2*cur+1].lval) tree[cur].left1+=tree[2*cur+1].left1;tree[cur].right1=tree[2*cur+1].right1;if(tree[cur].right1==tree[2*cur+1].r-tree[2*cur+1].l+1&&tree[2*cur].rval>tree[2*cur+1].lval) tree[cur].right1+=tree[2*cur].right1;tree[cur].all1=max(tree[2*cur].all1,tree[2*cur+1].all1);if(tree[2*cur].rval>tree[2*cur+1].lval) tree[cur].all1=max(tree[cur].all1,tree[2*cur].right1+tree[2*cur+1].left1);
}void build(int l,int r,int cur)
{int m;tree[cur].l=l;tree[cur].r=r;if(l==r){tree[cur].lval=val[mp2[l]];tree[cur].rval=val[mp2[l]];tree[cur].left0=1;tree[cur].right0=1;tree[cur].all0=1;tree[cur].left1=1;tree[cur].right1=1;tree[cur].all1=1;return;}m=(l+r)/2;build(l,m,2*cur);build(m+1,r,2*cur+1);pushup(cur);
}void queryII(int pl,int pr,int op,int &lval,int &rval,int &left,int &right,int &all,int cur)
{int llval,lrval,lleft,lright,lall;int rlval,rrval,rleft,rright,rall;//printf("%d %d %d %d\n",pl,pr,tree[cur].l,tree[cur].r);if(pl==tree[cur].l&&tree[cur].r==pr)//{lval=tree[cur].lval;rval=tree[cur].rval;if(op==0){left=tree[cur].left0;right=tree[cur].right0;all=tree[cur].all0;}else{left=tree[cur].left1;right=tree[cur].right1;all=tree[cur].all1;}//printf("gou: %d %d %d %d\n",pl,pr,lval,rval);return;}if(pr<=tree[2*cur].r){queryII(pl,pr,op,lval,rval,left,right,all,2*cur);}else if(pl>=tree[2*cur+1].l){queryII(pl,pr,op,lval,rval,left,right,all,2*cur+1);}else{queryII(pl,tree[2*cur].r,op,llval,lrval,lleft,lright,lall,2*cur);queryII(tree[2*cur+1].l,pr,op,rlval,rrval,rleft,rright,rall,2*cur+1);lval=llval,rval=rrval;left=lleft;if(op==0&&left==tree[2*cur].r-pl+1&&lrval<rlval) left+=rleft;else if(op==1&&left==tree[2*cur].r-pl+1&&lrval>rlval) left+=rleft;right=rright;if(op==0&&right==pr-tree[2*cur+1].l+1&&lrval<rlval) right+=lright;else if(op==1&&right==pr-tree[2*cur+1].l+1&&lrval>rlval) right+=lright;all=max(lall,rall);if(op==0&&lrval<rlval) all=max(all,lright+rleft);else if(op==1&&lrval>rlval) all=max(all,lright+rleft);}
}int queryI(int u,int v)
{int res;int lval0,rval0,left0,right0,all0,plval0,prval0,pleft0,pright0,pall0,tlval0,trval0,tleft0,tright0,tall0;int lval1,rval1,left1,right1,all1,plval1,prval1,pleft1,pright1,pall1,tlval1,trval1,tleft1,tright1,tall1;res=0,plval1=N,plval0=-N,pleft0=0,pleft1=0;while(top[u]!=top[v]){if(deep[top[u]]>deep[top[v]]){queryII(mp1[top[u]],mp1[u],1,lval1,rval1,left1,right1,all1,1);//printf("#1u %d %d\n",mp1[top[u]],mp1[u]);//printf("#1u %d %d %d %d %d\n",lval1,rval1,left1,right1,all1);res=max(res,all1);if(rval1>plval1) res=max(res,right1+pleft1);if(left1==mp1[u]-mp1[top[u]]+1&&rval1>plval1) pleft1=left1+pleft1;else pleft1=left1;res=max(res,pleft1);plval1=lval1;u=fa[top[u]];}else{queryII(mp1[top[v]],mp1[v],0,lval0,rval0,left0,right0,all0,1);//printf("#1v %d %d\n",mp1[top[v]],mp1[v]);//printf("#1v %d %d %d %d %d\n",lval0,rval0,left0,right0,all0);res=max(res,all0);if(rval0<plval0) res=max(res,right0+pleft0);if(left0==mp1[v]-mp1[top[v]]+1&&rval0<plval0) pleft0=left0+pleft0;else pleft0=left0;res=max(res,pleft0);plval0=lval0;v=fa[top[v]];}}if(deep[u]>deep[v]){queryII(mp1[v],mp1[u],1,lval1,rval1,left1,right1,all1,1);//printf("#2u %d %d %d %d %d\n",lval1,rval1,left1,right1,all1);res=max(res,all1);if(rval1>plval1) res=max(res,right1+pleft1);if(left1==mp1[u]-mp1[v]+1&&rval1>plval1) pleft1=left1+pleft1;else pleft1=left1;res=max(res,pleft1);plval1=lval1;//printf("%d %d %d\n",plval0,pleft1,pleft0);if(plval1<plval0) res=max(res,pleft1+pleft0);}else{queryII(mp1[u],mp1[v],0,lval0,rval0,left0,right0,all0,1);//printf("#2v %d %d %d %d %d\n",lval0,rval0,left0,right0,all0);res=max(res,all0);if(rval0<plval0) res=max(res,right0+pleft0);if(left0==mp1[v]-mp1[u]+1&&rval0<plval0) pleft0=left0+pleft0;else pleft0=left0;res=max(res,pleft0);plval0=lval0;//printf("%d %d %d\n",plval0,pleft1,pleft0);if(plval1<plval0) res=max(res,pleft1+pleft0);}return res;
}int main()
{int t,cas,i,u,v;scanf("%d",&t);for(cas=1;cas<=t;cas++){scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&val[i]);}memset(first,-1,sizeof(first));num=0;for(i=2;i<=n;i++){scanf("%d",&u);addedge(u,i);addedge(i,u);}fa[1]=-1,deep[1]=1;dfsI(1);num=0;dfsII(1,1);build(1,n,1);printf("Case #%d:\n",cas);scanf("%d",&q);while(q--){scanf("%d%d",&u,&v);printf("%d\n",queryI(u,v));}if(cas<t) printf("\n");}return 0;
}/*
100
10
1 2 3 4 5 6 7 8 9 106 2 5 1 5 1 7 10 4
*/

 

这篇关于The LCIS on the Tree HDU - 4718的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/736174

相关文章

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

hdu 3790 (单源最短路dijkstra)

题意: 每条边都有长度d 和花费p,给你起点s 终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 解析: 考察对dijkstra的理解。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstrin

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时