【BZOJ5469】[FJOI2018]領導集團問題(動態(tài)規(guī)劃,線段樹合并)
題面
BZOJ
洛谷
題解
題目就是讓你在樹上找一個最大的點集,使得兩個點如果存在祖先關系,那么就要滿足祖先的權值要小于等于兒子的權值。
首先離散權值。
考慮一個暴力\(dp\),設\(f[i][j]\)表示以\(i\)為根,子樹中被選擇的最小值為\(j\)時能夠被選出的最大點樹。然后xjb轉移一下就寫出了一個\(O(n^3)\)的優(yōu)秀做法。
然后把狀態(tài)從恰好變成至少,然后就得到了一個\(O(n^2)\)的做法。
考慮\(O(n^2)\)的\(dp\),本質上就是在維護一個后綴的最大值。
不難發(fā)現(xiàn)后綴最大值一定是不降的。
考慮對于后綴進行差分,每次相當于現(xiàn)在\(w[i]\)位置加一,然后往前更新一段,直到下一個差分數(shù)組上有\(1\)的位置。
那么用線段樹合并就可以解決這個問題,給\(w[i]\)位置加一,然后線段樹上二分找到上一個為\(1\)的位置然后把它減一就好了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAX 200200
inline int read()
{int x=0;bool t=false;char ch=getchar();while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();if(ch=='-')t=true,ch=getchar();while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();return t?-x:x;
}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int n,ans,w[MAX],S[MAX],tot,rt[MAX];
int ls[MAX*18],rs[MAX*18],t[MAX*18],node;
void Modify(int &x,int l,int r,int p)
{if(!x)x=++node;t[x]+=1;if(l==r)return;int mid=(l+r)>>1;if(p<=mid)Modify(ls[x],l,mid,p);else Modify(rs[x],mid+1,r,p);
}
bool Flag;
void Calc(int x)
{if(!x)return;t[x]-=1;if(t[rs[x]])Calc(rs[x]);else Calc(ls[x]);
}
void Minus(int x,int l,int r,int p)
{if(l==r)return;int mid=(l+r)>>1;if(p<=mid)Minus(ls[x],l,mid,p);else{Minus(rs[x],mid+1,r,p);if(!Flag&&t[ls[x]])Flag=true,Calc(ls[x]);}if(Flag)t[x]-=1;
}
void Merge(int &x,int &y)
{if(!x||!y){x|=y;return;}t[x]+=t[y];Merge(ls[x],ls[y]);Merge(rs[x],rs[y]);
}
void dfs(int u)
{for(int i=h[u];i;i=e[i].next)dfs(e[i].v),Merge(rt[u],rt[e[i].v]);Modify(rt[u],1,tot,w[u]);Flag=false;Minus(rt[u],1,tot,w[u]);
}
int main()
{n=read();for(int i=1;i<=n;++i)S[++tot]=w[i]=read();for(int i=2;i<=n;++i)Add(read(),i);S[++tot]=1e9+1;sort(&S[1],&S[tot+1]);tot=unique(&S[1],&S[tot+1])-S-1;for(int i=1;i<=n;++i)w[i]=lower_bound(&S[1],&S[tot+1],w[i])-S;dfs(1);printf("%d\n",t[rt[1]]);return 0;
}
轉載于:https://www.cnblogs.com/cjyyb/p/10446523.html
總結
以上是生活随笔為你收集整理的【BZOJ5469】[FJOI2018]领导集团问题(动态规划,线段树合并)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。