P4556 [Vani有約會]雨天的尾巴 /【模板】線段樹合併
阿新 • • 發佈:2020-07-20
線段樹合併
線段樹合併即合併兩顆權值線段樹,合併方法非常簡單
但是這道題我調了很久
原因:陣列開小了QAQ
線段樹合併一般陣列開\(3nlogn\)(更大也無傷大雅)
我\(ls\),\(rs\)陣列開小了,導致玄學錯誤,結果暈頭轉向,最後才發現數組開小了
\(C++\)陣列開小很多情況下不報錯,因為它去呼叫其他陣列的無用空間了,以至於難以發現錯誤
下次看到難以理解的錯誤(比如輸出值在更改一個無關緊要的語句後不恆定),一定要去看陣列(一個數組一個數組看過來)!
同時,可以將相同種類的陣列放在一起
放程式碼吧。。。
#include<bits/stdc++.h> #define N 200005 #define S 100000 #define pr pair<int,int> using namespace std; int n,m,x,y; int cnt,tot,head[N],nxt[N],d[N],ac[N],lca[N],F[N],rt[N],ans[N]; int ls[N*25],rs[N*25],tree[N*25],id[N*25]; bool leaf[N*25]; vector<pr>q[N]; struct node { int x,y,z; }e[N]; void add(int x,int y) { tot++; d[tot]=y; nxt[tot]=head[x]; head[x]=tot; } int getf(int x) { if (ac[x]==x) return x; return ac[x]=getf(ac[x]); } void tarjan(int u,int f) { ac[u]=u; for (int i=head[u];i;i=nxt[i]) { int v=d[i]; if (v==f) continue; tarjan(v,u); ac[v]=u; F[v]=u; } for (vector<pr>::iterator it=q[u].begin();it!=q[u].end();it++) if (ac[it->first]) lca[it->second]=getf(ac[it->first]); } void change(int &p,int l,int r,int x,int z) { if (!p) p=++cnt; if (l==r) { tree[p]+=z; id[p]=l; leaf[p]=true; return; } int mid=(l+r) >> 1; if (x<=mid) change(ls[p],l,mid,x,z); else change(rs[p],mid+1,r,x,z); if (tree[ls[p]]>tree[rs[p]]||tree[ls[p]]==tree[rs[p]]&&id[ls[p]]<id[rs[p]]) { tree[p]=tree[ls[p]]; id[p]=id[ls[p]]; } else { tree[p]=tree[rs[p]]; id[p]=id[rs[p]]; } } int merge(int x,int y) { if (!x||!y) return x|y; if (leaf[x]&&leaf[y]) { tree[x]+=tree[y]; return x; } ls[x]=merge(ls[x],ls[y]); rs[x]=merge(rs[x],rs[y]); if (tree[ls[x]]>tree[rs[x]]||tree[ls[x]]==tree[rs[x]]&&id[ls[x]]<id[rs[x]]) { tree[x]=tree[ls[x]]; id[x]=id[ls[x]]; } else { tree[x]=tree[rs[x]]; id[x]=id[rs[x]]; } return x; } void dfs(int u) { for (int i=head[u];i;i=nxt[i]) { int v=d[i]; if (v==F[u]) continue; dfs(v); rt[u]=merge(rt[u],rt[v]); } ans[u]=id[rt[u]]; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<n;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } for (int i=1;i<=m;i++) { scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z); q[e[i].x].push_back(make_pair(e[i].y,i)); q[e[i].y].push_back(make_pair(e[i].x,i)); } tarjan(1,0); for (int i=1;i<=m;i++) { change(rt[e[i].x],1,S,e[i].z,1); change(rt[e[i].y],1,S,e[i].z,1); change(rt[lca[i]],1,S,e[i].z,-1); if (F[lca[i]]) change(rt[F[lca[i]]],1,S,e[i].z,-1); } dfs(1); for (int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }