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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

洛谷 - P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并(树上差分+线段树合并)

發(fā)布時(shí)間:2024/4/11 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 洛谷 - P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并(树上差分+线段树合并) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目鏈接:點(diǎn)擊查看

題目大意:給出一棵樹,再給出 m 次操作,每次操作會(huì)選擇兩個(gè)點(diǎn) ( x , y ) ,使得這條路徑上的所有點(diǎn)的種類 z 加一,最后問每個(gè)點(diǎn)的哪個(gè)種類出現(xiàn)的頻率最高,若多個(gè)種類出現(xiàn)頻率相同時(shí),輸出編號最小的

題目分析:線段樹合并模板題,感覺 update 函數(shù)和主席樹非常像,所以就仿照主席樹的寫法去實(shí)現(xiàn)的,相比于正常的線段樹來說,僅僅多了一個(gè) merge 函數(shù)用于合并兩棵線段樹罷了,時(shí)間復(fù)雜度是嚴(yán)格 nlogn 的,因?yàn)榫S護(hù)的時(shí)候采用的是樹上差分,即:

  • x + 1
  • y + 1
  • lca( x , y ) - 1
  • fa[ lca( x , y ) ] -1
  • 對于某次操作共需要維護(hù) 4 條鏈,也就是說總共需要維護(hù) 4 * m * logn 條鏈,所以空間需要開 50 倍才夠,對于這個(gè)題目而言,在每個(gè)節(jié)點(diǎn)上都維護(hù)一棵線段樹然后 dfs 合并即可

    代碼:
    ?

    //#pragma GCC optimize(2) //#pragma GCC optimize("Ofast","inline","-ffast-math") //#pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;vector<int>node[N];int ans[N];int dp[N][20],deep[N];void dfs(int u,int fa,int dep) {deep[u]=dep;dp[u][0]=fa;for(int i=1;i<20;i++)dp[u][i]=dp[dp[u][i-1]][i-1];for(auto v:node[u]){if(v==fa)continue;dfs(v,u,dep+1);} }int LCA(int x,int y) {if(deep[x]<deep[y])swap(x,y);for(int i=19;i>=0;i--)if(deep[x]-deep[y]>=(1<<i))x=dp[x][i];if(x==y)return x;for(int i=19;i>=0;i--)if(dp[x][i]!=dp[y][i]){x=dp[x][i];y=dp[y][i];}return dp[x][0]; }struct Node {int l,r,mmax,id; }tree[N*50];int root[N],tot;void pushup(int k) {if(tree[tree[k].l].mmax>=tree[tree[k].r].mmax){tree[k].mmax=tree[tree[k].l].mmax;tree[k].id=tree[tree[k].l].id;}else{tree[k].mmax=tree[tree[k].r].mmax;tree[k].id=tree[tree[k].r].id;} }void update(int& k,int pos,int val,int l,int r) {if(!k)k=++tot;assert(tot<N*50);if(l==r){tree[k].mmax+=val;tree[k].id=l;return;}int mid=l+r>>1;if(pos<=mid)update(tree[k].l,pos,val,l,mid);elseupdate(tree[k].r,pos,val,mid+1,r);pushup(k); }void merge(int& a,int b,int l,int r) {if(!a||!b){a=a+b;return;}if(l==r){tree[a].mmax+=tree[b].mmax;tree[a].id=l;return;}int mid=l+r>>1;merge(tree[a].l,tree[b].l,l,mid);merge(tree[a].r,tree[b].r,mid+1,r);pushup(a); }void dfs_ans(int u,int fa) {for(auto v:node[u]){if(v==fa)continue;dfs_ans(v,u);merge(root[u],root[v],1,100000);}if(tree[root[u]].mmax)ans[u]=tree[root[u]].id; }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}dfs(1,0,0);while(m--){int x,y,z;scanf("%d%d%d",&x,&y,&z);int lca=LCA(x,y); update(root[x],z,1,1,100000);update(root[y],z,1,1,100000);update(root[lca],z,-1,1,100000);update(root[dp[lca][0]],z,-1,1,100000);}dfs_ans(1,0);for(int i=1;i<=n;i++)printf("%d\n",ans[i]);return 0; }

    ?

    總結(jié)

    以上是生活随笔為你收集整理的洛谷 - P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并(树上差分+线段树合并)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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