bzoj3307:雨天的尾巴

传送门

树上差分+线段树合并+离散化
对于修改的路径,树上差分就好了
代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<tr1/unordered_map>
#include<algorithm>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=1e5+10;
int dep[maxn],n,m,id,tot,pre[maxn*2],rt[maxn],ls[maxn*50],f[maxn][20],x[maxn],y[maxn],z[maxn],nid[maxn];
int rs[maxn*50],mx[maxn*50],mxid[maxn*50],nxt[maxn*2],h[maxn],cnt,ans[maxn],w[maxn];tr1::unordered_map<int,int>mp;
bool vis[maxn];
void add(int x,int y)
{
    pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt;
    pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt;
}
void dfs(int x,int fa)
{
    for(rg int i=1;i<20;i++)
    {
        if((1<<i)>dep[x])break;
        f[x][i]=f[f[x][i-1]][i-1];
    }
    for(rg int i=h[x];i;i=nxt[i])
        if(pre[i]!=fa)f[pre[i]][0]=x,dep[pre[i]]=dep[x]+1,dfs(pre[i],x);
}
int lca(int x,int y)
{
    if(dep[x]>dep[y])swap(x,y);
    int poor=dep[y]-dep[x];
    for(rg int i=19;i>=0;i--)if(poor&(1<<i))y=f[y][i];
    if(x==y)return x;
    for(rg int i=19;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    return x==y?x:f[x][0];
}
void update(int x)
{
    if(mx[ls[x]]>mx[rs[x]]||(mx[ls[x]]==mx[rs[x]]&&mxid[ls[x]]<mxid[rs[x]]))mx[x]=mx[ls[x]],mxid[x]=mxid[ls[x]];
    else if(mx[ls[x]]<mx[rs[x]]||(mx[ls[x]]==mx[rs[x]]&&mxid[ls[x]]>mxid[rs[x]]))mx[x]=mx[rs[x]],mxid[x]=mxid[rs[x]];
}
void change(int &k,int l,int r,int a,int b)
{
    if(!k)k=++id;int mid=(l+r)>>1;
    if(l==r){mx[k]+=b,mxid[k]=mx[k]?l:0;return ;}
    if(a<=mid)change(ls[k],l,mid,a,b);
    else change(rs[k],mid+1,r,a,b);
    update(k);
}
int merge(int x,int y,int l,int r)
{
    if(!x||!y)return x+y;
    int mid=(l+r)>>1;
    ls[x]=merge(ls[x],ls[y],l,mid);
    rs[x]=merge(rs[x],rs[y],mid+1,r);
    if(l==r)mx[x]+=mx[y],mxid[x]=mx[x]?l:0;else update(x);
    return x;
}
void solve(int x,int fa)
{
    for(rg int i=h[x];i;i=nxt[i])
        if(pre[i]!=fa)
        {
            solve(pre[i],x);
            rt[x]=merge(rt[x],rt[pre[i]],1,tot);
        }
    ans[x]=nid[mxid[rt[x]]];
}
int main()
{
    read(n),read(m);
    for(rg int i=1,x,y;i<n;i++)read(x),read(y),add(x,y);
    dfs(1,0);
    for(rg int i=1;i<=m;i++)read(x[i]),read(y[i]),read(z[i]),w[i]=z[i];
    sort(w+1,w+m+1);
    for(rg int i=1;i<=m;i++)if(!mp[w[i]])mp[w[i]]=++tot,nid[tot]=w[i];
    for(rg int i=1;i<=m;i++)
    {
        int fa=lca(x[i],y[i]);
        change(rt[x[i]],1,tot,mp[z[i]],1),change(rt[y[i]],1,tot,mp[z[i]],1),
        change(rt[fa],1,tot,mp[z[i]],-1),change(rt[f[fa][0]],1,tot,mp[z[i]],-1);
    }
    solve(1,0);
    for(rg int i=1;i<=n;i++)printf("%d
",ans[i]);
}
原文地址:https://www.cnblogs.com/lcxer/p/10604150.html