zoukankan      html  css  js  c++  java
  • [CF490F]Treeland Tour(线段树合并)

    树上LIS:树上找一条简单路径的子序列使点权严格单增,最大化长度。

    原题数据过小,用线段树合并可以做到$O(nlog n)$。

    每个点用一棵线段树维护以每个权值为结尾的LIS最长长度,线段树合并时更新子序列不包含当前点时的最大值,再线段树上区间询问得到包含时的最大值并更新线段树。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define lson ls[x],L,mid
     4 #define rson rs[x],mid+1,R
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
     7 using namespace std;
     8 
     9 const int N=100010;
    10 int n,u,v,ans,nd,cnt,tot,lis[N*25],lds[N*25],ls[N*25],rs[N*25];
    11 int h[N],to[N<<1],nxt[N<<1],rt[N],a[N],b[N];
    12 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
    13 
    14 int merge(int x,int y){
    15     if (!x || !y) return x|y;
    16     lis[x]=max(lis[x],lis[y]); lds[x]=max(lds[x],lds[y]);
    17     ans=max(ans,max(lis[ls[x]]+lds[rs[y]],lds[rs[x]]+lis[ls[y]]));
    18     ls[x]=merge(ls[x],ls[y]); rs[x]=merge(rs[x],rs[y]); return x;
    19 }
    20 
    21 void mdf(int &x,int L,int R,int p,int k,int a[]){
    22     if (!x) x=++nd;
    23     a[x]=max(a[x],k); int mid=(L+R)>>1;
    24     if (L==R) return;
    25     if (p<=mid) mdf(lson,p,k,a); else mdf(rson,p,k,a);
    26 }
    27 
    28 int que(int x,int L,int R,int l,int r,int a[]){
    29     if (L==l && r==R) return a[x];
    30     int mid=(L+R)>>1;
    31     if (r<=mid) return que(lson,l,r,a);
    32     else if (l>mid) return que(rson,l,r,a);
    33         else return max(que(lson,l,mid,a),que(rson,mid+1,r,a));
    34 }
    35 
    36 void dfs(int x,int fa){
    37     For(i,x) if ((k=to[i])!=fa) dfs(k,x);
    38     int s1=0,s2=0,t1,t2;
    39     For(i,x) if ((k=to[i])!=fa){
    40         t1=a[x]>1 ? que(rt[k],1,tot,1,a[x]-1,lis) : 0;
    41         t2=a[x]<tot ? que(rt[k],1,tot,a[x]+1,tot,lds) : 0;
    42         rt[x]=merge(rt[x],rt[k]); ans=max(ans,max(s1+t2+1,s2+t1+1));
    43         s1=max(s1,t1); s2=max(s2,t2);
    44     }
    45     mdf(rt[x],1,tot,a[x],s1+1,lis); mdf(rt[x],1,tot,a[x],s2+1,lds);
    46 }
    47 
    48 int main(){
    49     freopen("490F.in","r",stdin);
    50     freopen("490F.out","w",stdout);
    51     scanf("%d",&n);
    52     rep(i,1,n) scanf("%d",&a[i]),b[i]=a[i];
    53     sort(b+1,b+n+1); tot=unique(b+1,b+n+1)-b-1;
    54     rep(i,1,n) a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
    55     rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u);
    56     dfs(1,0); printf("%d
    ",ans);
    57     return 0;
    58 }
  • 相关阅读:
    codeforces#1310B. Double Elimination(动态规划)
    codeforces#1300E. Water Balance(贪心)
    带权并查集
    codeforces#1295D. Same GCDs(数论/莫比乌斯)
    jsp实现图片换行显示
    codeforces#1257 F. Make Them Similar ( 经典中间相遇问题 )
    codeforces#1248D2. The World Is Just a Programming Task(括号匹配转化为折线处理)
    codeforces#1251E2. Voting (Hard Version)(贪心)
    codeforces#1249F. Maximum Weight Subset(树上dp)
    hdu6731 Angle Beats(ccpc秦皇岛A,计算几何)
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10575651.html
Copyright © 2011-2022 走看看