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

        歡迎訪問 生活随笔!

        生活随笔

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

        编程问答

        jzoj3338-[NOI2013模拟]法法塔的奖励【权值线段树,线段树合并】

        發布時間:2023/12/3 编程问答 44 豆豆
        生活随笔 收集整理的這篇文章主要介紹了 jzoj3338-[NOI2013模拟]法法塔的奖励【权值线段树,线段树合并】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

        正題


        題目大意

        一棵樹,對于每個點,求從任何一個在該點的子樹為頭,以該點為結尾的序列必須選擇這個點的最長不降子序列。


        解題思路

        首先我們使用權值線段樹計算答案每個點(l,r,w)(l,r,w)(l,r,w)表示以l~rl\sim rlr為結尾最長的不降升子序列長度。

        然后利用線段樹維護,每次跑完子節點之后將線段樹合并到父節點上來計算答案。

        時間復雜度O(nlogn)O(n\ log\ n)O(n?log?n)


        codecodecode

        #pragma GCC optimize(2) %:pragma GCC optimize(3) %:pragma GCC optimize("Ofast") %:pragma GCC optimize("inline") #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int N=101000; int n,rt[N],tot,ls[N],ans[N],w[N]; struct Edge_node{int to,next; }a[N]; struct Tree_node{int w,l,r,lson,rson; }; vector<int> q[N],c[N]; struct Line_cut_tree{Tree_node t[N*20];int tot;#define ls t[x].lson#define rs t[x].rsonint Ask(int x,int l,int r,int L,int R){if(!x) return 0; if(L==l&&R==r)return t[x].w;int mid=(L+R)/2;if(r<=mid) return Ask(ls,l,r,L,mid);else if(l>mid) return Ask(rs,l,r,mid+1,R);else return max(Ask(ls,l,mid,L,mid),Ask(rs,mid+1,r,mid+1,R));}void Change(int &x,int pos,int z,int L,int R){if(!x) x=++tot;if(L==R){t[x].w=max(z,t[x].w);return;}int mid=(L+R)/2;if(pos<=mid) Change(ls,pos,z,L,mid);else if(pos>mid) Change(rs,pos,z,mid+1,R);t[x].w=max(t[ls].w,t[rs].w);}int merge(int x,int y,int L,int R){if(!x||!y)return x+y;t[x].w=max(t[x].w,t[y].w);if(L==R)return x;int mid=(L+R)/2;t[x].lson=merge(t[x].lson,t[y].lson,L,mid);t[x].rson=merge(t[x].rson,t[y].rson,mid+1,R);return x;}#undef ls#undef rs }Tree; void addl(int x,int y) {a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot; } void dfs(int x) {int root=0;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;dfs(y);root=Tree.merge(root,rt[y],1,n);}ans[x]=Tree.Ask(root,1,w[x],1,n)+1;Tree.Change(root,w[x],ans[x],1,n);rt[x]=root; } int main() {scanf("%d",&n);for(int i=1;i<=n;i++){int x;scanf("%d",&x);if(i==1) continue;addl(x,i);}for(int i=1;i<=n;i++)scanf("%d",&w[i]);dfs(1);for(int i=1;i<=n;i++)printf("%d ",ans[i]); }

        總結

        以上是生活随笔為你收集整理的jzoj3338-[NOI2013模拟]法法塔的奖励【权值线段树,线段树合并】的全部內容,希望文章能夠幫你解決所遇到的問題。

        如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。