P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 题解
作者:互联网
Link
P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
Solve
对于每个节点都减一颗权值线段树,然后再用差分的做法,最后统计答案的时候把线段树都合并起来,事实更新最优解
这道题主要是模板,细节蛮多的,要注意
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=100005,maxe=200005;
int N,M;
int cnt,lnk[maxn],nxt[maxe],son[maxe];
int tot,size[maxn],top[maxn],dep[maxn],max_son[maxn],F[maxn],root[maxn],Ans[maxn];
int X[maxn],Y[maxn],Z[maxn],MAXR;
struct node{
int lson,rson,x;
LL tot;
}c[6000005];
inline void add_e(int x,int y){son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;}
void DFS1(int x,int fa){
size[x]=1;int max_x=-(1<<30);
for(int j=lnk[x];j;j=nxt[j]){
if(son[j]==fa)continue;
dep[son[j]]=dep[x]+1;F[son[j]]=x;
DFS1(son[j],x);
size[x]+=size[son[j]];
if(size[son[j]]>max_x)max_x=size[son[j]],max_son[x]=son[j];
}
return ;
}
void DFS2(int x,int fa,int topf){
top[x]=topf;
for(int j=lnk[x];j;j=nxt[j]){
if(son[j]==fa)continue;
if(son[j]==max_son[x])DFS2(son[j],x,topf);
else DFS2(son[j],x,son[j]);
}
}
int LCA(int x,int y){
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=F[top[x]];
}
return dep[x]<dep[y]?x:y;
}
inline int build(){
++tot;c[tot].lson=c[tot].rson=c[tot].tot=c[tot].x=0;
return tot;
}
inline void push_up(int x){
if(c[c[x].lson].tot>=c[c[x].rson].tot)c[x].tot=c[c[x].lson].tot,c[x].x=c[c[x].lson].x;
else c[x].tot=c[c[x].rson].tot,c[x].x=c[c[x].rson].x;
return ;
}
int change(int x,int l,int r,int pos,int val){
if(!x)x=build();
if(l==r){c[x].tot+=val;c[x].x=l;return x;}
int mid=(r-l>>1)+l;
if(pos<=mid) c[x].lson=change(c[x].lson,l,mid,pos,val);
else c[x].rson=change(c[x].rson,mid+1,r,pos,val);
push_up(x);
return x;
}
int merge(int p,int q,int l,int r){
if(!p)return q;if(!q)return p;
if(l==r){c[p].tot+=c[q].tot;c[p].x=l;return p;}
int mid=(r-l>>1)+l;
c[p].lson=merge(c[p].lson,c[q].lson,l,mid);
c[p].rson=merge(c[p].rson,c[q].rson,mid+1,r);
push_up(p);
return p;
}
void DFS3(int x,int fa){
for(int j=lnk[x];j;j=nxt[j]){
if(son[j]==fa)continue;
DFS3(son[j],x);root[x]=merge(root[x],root[son[j]],1,MAXR);
}
if(c[root[x]].tot)Ans[x]=c[root[x]].x;
return ;
}
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
int main(){
freopen("P4556.in","r",stdin);
freopen("P4556.out","w",stdout);
N=read();M=read();
for(int i=1;i<N;i++){
int x=read(),y=read();
add_e(x,y);add_e(y,x);
}
dep[1]=1;DFS1(1,0);
DFS2(1,0,1);
for(int i=1;i<=M;i++){
X[i]=read(),Y[i]=read(),Z[i]=read();MAXR=max(MAXR,Z[i]);
}
for(int i=1;i<=M;i++){
int lca=LCA(X[i],Y[i]);
root[X[i]]=change(root[X[i]],1,MAXR,Z[i],1);
root[Y[i]]=change(root[Y[i]],1,MAXR,Z[i],1);
root[lca]=change(root[lca],1,MAXR,Z[i],-1);
if(F[lca])root[F[lca]]=change(root[F[lca]],1,MAXR,Z[i],-1);
}
DFS3(1,0);
for(int i=1;i<=N;i++)printf("%d\n",Ans[i]);
return 0;
}
标签:ch,int,题解,rson,tot,son,maxn,P4556,Vani 来源: https://www.cnblogs.com/martian148/p/14083836.html