zoukankan      html  css  js  c++  java
  • BZOJ3307 雨天的尾巴

    题目链接:戳我

    树上链修改->差分
    每一个节点都开一个权值线段树,最后从下往上合并qwq

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define MAXN 200010
    using namespace std;
    int t,n,m,cnt,cur_cnt;
    int maxx[MAXN<<5],head[MAXN],ans[MAXN],dep[MAXN],x[MAXN],y[MAXN],z[MAXN],cur[MAXN],id[MAXN];
    int fa[MAXN][21],rt[MAXN],ls[MAXN<<5],rs[MAXN<<5];
    struct Edge{int nxt,to;}edge[MAXN<<1];
    inline void add(int from,int to){edge[++t].nxt=head[from],edge[t].to=to,head[from]=t;}
    inline void push_up(int x){maxx[x]=max(maxx[ls[x]],maxx[rs[x]]);}
    inline void modify(int &x,int l,int r,int pos,int k)
    {
        if(!x) x=++cnt;
        if(l==r) {maxx[x]+=k;return;}
        int mid=(l+r)>>1;
        if(pos<=mid) modify(ls[x],l,mid,pos,k);
        else modify(rs[x],mid+1,r,pos,k);
        push_up(x);
    }
    inline int merge(int x,int y,int l,int r)
    {
        if(!x||!y) return x+y;
        if(l==r) {maxx[x]+=maxx[y];return x;}
        int mid=(l+r)>>1;
        ls[x]=merge(ls[x],ls[y],l,mid);
        rs[x]=merge(rs[x],rs[y],mid+1,r);
        push_up(x);
        return x;
    }
    inline int query(int x,int l,int r)
    {
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(maxx[x]==maxx[ls[x]]) return query(ls[x],l,mid);
        else return query(rs[x],mid+1,r);
    }
    inline void dfs1(int x,int ff)
    {
        for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==fa[x][0]) continue;
            dep[v]=dep[x]+1;fa[v][0]=x;
            dfs1(v,x);
        }
    }
    inline int lca(int x,int y)
    {
        if(dep[x]<dep[y]) swap(x,y);
        int tt=dep[x]-dep[y];
        for(int i=0;i<21;i++)
            if(tt&(1<<i))
                x=fa[x][i];
        if(x==y) return x;
        for(int i=20;i>=0;i--)
            if(fa[x][i]!=fa[y][i])
                x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    inline void solve(int x,int ff)
    {
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==ff) continue;
            solve(v,x);
            rt[x]=merge(rt[x],rt[v],1,cur_cnt);
        }
        if(!maxx[rt[x]]) ans[x]=0;
        else ans[x]=id[query(rt[x],1,cur_cnt)];
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        for(int i=1;i<=m;i++) scanf("%d%d%d",&x[i],&y[i],&z[i]);
        memcpy(cur,z,sizeof(z));
        sort(&cur[1],&cur[1+m]);
        cur_cnt=unique(&cur[1],&cur[1+m])-cur-1;
        for(int i=1;i<=m;i++)
        {
            int kkk=lower_bound(&cur[1],&cur[1+cur_cnt],z[i])-cur;
            id[kkk]=z[i];
            z[i]=kkk;
        }
        dfs1(1,1);
        for(int i=1;i<=m;i++)
        {
            modify(rt[x[i]],1,cur_cnt,z[i],1);
            modify(rt[y[i]],1,cur_cnt,z[i],1);
            int LCA=lca(x[i],y[i]);
            modify(rt[LCA],1,cur_cnt,z[i],-1);
            if(fa[LCA]) 
                modify(rt[fa[LCA][0]],1,cur_cnt,z[i],-1);
        }
        solve(1,1);
        for(int i=1;i<=n;i++)
            printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    bzoj 1406 数论
    bzoj 1927 网络流
    【HNOI】 攻城略池 tree-dp
    【HNOI】五彩斑斓 模拟
    linux下nano命令大全
    CentOS7.6下安装MySQL
    CentOS7.6下安装Oracle JDK
    Vue报错type check failed for prop
    图像分割
    提升方法(boosting)详解
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10326903.html
Copyright © 2011-2022 走看看