日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【牛客 - 368B】选点(dfs序,LIS 或 dfs序 + 树状数组 + 离散化,树状数组求LIS的方法)

發(fā)布時間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【牛客 - 368B】选点(dfs序,LIS 或 dfs序 + 树状数组 + 离散化,树状数组求LIS的方法) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題干:
?

有一棵n個節(jié)點的二叉樹,1為根節(jié)點,每個節(jié)點有一個值wi。現(xiàn)在要選出盡量多的點。

對于任意一棵子樹,都要滿足:

如果選了根節(jié)點的話,在這棵子樹內(nèi)選的其他的點都要比根節(jié)點的值

如果在左子樹選了一個點,在右子樹中選的其他點要比它

輸入描述:

?

第一行一個整數(shù)n。

第二行n個整數(shù)wi,表示每個點的權(quán)值。

接下來n行,每行兩個整數(shù)a,b。第i+2行表示第i個節(jié)點的左右兒子節(jié)點。沒有為0。

n,a,b≤105,?2×109≤wi≤2×109n,a,b≤105,?2×109≤wi≤2×109

輸出描述:

一行一個整數(shù)表示答案。

示例1

輸入

復制

5 1 5 4 2 3 3 2 4 5 0 0 0 0 0 0

輸出

復制

3

解題報告:

? 注意依據(jù)題意,需要先遍歷右子樹,再遍歷左子樹。或者存權(quán)值直接存負值,然后先遍歷左子樹再遍歷右子樹(即正常dfs序)也可以。

AC代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<ctime> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; int dfn[MAX],in[MAX],out[MAX]; int id,n; int a[MAX],b[MAX]; int ans[MAX]; int w[MAX]; void dfs(int cur,int root) {dfn[++id] = cur;in[cur] = id;if(b[cur] != 0)dfs(b[cur],cur);if(a[cur] != 0)dfs(a[cur],cur);out[cur] = id; } int DP() {int len = 0;for(int i = 1; i<=id; i++) dfn[i] = w[dfn[i]];ans[++len] = dfn[1];for(int i = 2; i<=id; i++) {if(dfn[i] > ans[len]) ans[++len] = dfn[i];else {int pos = lower_bound(ans+1,ans+len+1,dfn[i]) - ans;ans[pos] = dfn[i];}}return len; } int main() {cin>>n;for(int i = 1; i<=n; i++) scanf("%d",w+i);for(int i = 1; i<=n; i++) scanf("%d%d",a+i,b+i);dfs(1,0);printf("%d\n",DP());return 0 ; }

AC代碼2:

#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int p[maxn], q[maxn], t[maxn]; int lson[maxn], rson[maxn], cnt, len; void dfs(int rt) {if (!rt)return;dfs(lson[rt]);dfs(rson[rt]);q[++cnt] = p[rt]*(-1); } int main() {int n;cin >> n;for (int i = 1; i <= n; i++)cin >> p[i];for (int i = 1; i <= n; i++) {int x, y;cin >> x >> y;lson[i] = x, rson[i] = y;}dfs(1);t[1] = q[1];for (int i = 2; i <= n; i++) {int cur = lower_bound(t + 1, t + 1 + len,q[i]) - t;t[cur] = q[i];len = max(len, cur);}cout << len << endl; }

還有一種解法(Orz大佬)

這個dfs序(因為是后序遍歷)完了之后是對離散化后的權(quán)值求最長下降子序列(也就是值是1~n,求最長下降子序列),

#include<bits/stdc++.h> using namespace std; const int N=100010; int W[N],A[N],h,B[N],lson[N],rson[N]; void dfs(int x){if (x==0){return;}dfs(lson[x]);dfs(rson[x]);A[++h]=W[x]; } struct Binary_Indexed_Tree{int n,bit[N];void Add(int i,int x){while (i>0){bit[i]=max(bit[i],x);i-=i&-i;}}int Query(int i){int res=0;while (i<=n){res=max(res,bit[i]);i+=i&-i;}return res;} }BIT; int main(){int n,i;scanf("%d",&n);for (i=1;i<=n;i++){scanf("%d",&W[i]);B[i]=W[i];}sort(B+1,B+1+n);int t=unique(B+1,B+1+n)-B-1;for (i=1;i<=n;i++){W[i]=lower_bound(B+1,B+1+t,W[i])-B;}for (i=1;i<=n;i++){scanf("%d%d",&lson[i],&rson[i]);}dfs(1);BIT.n=t;int Ans=1;for (i=1;i<=n;i++){int p=BIT.Query(A[i]+1);BIT.Add(A[i],p+1);Ans=max(Ans,p+1);}printf("%d\n",Ans);return 0; }

?

總結(jié)

以上是生活随笔為你收集整理的【牛客 - 368B】选点(dfs序,LIS 或 dfs序 + 树状数组 + 离散化,树状数组求LIS的方法)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。