• [BZOJ] 3307: 雨天的尾巴


    题意:给一颗树,每次在一条路径上增加一种物品,问每个点为根的子树中最多的物品的种类

    每个点维护一颗权值线段树,树上差分,复杂度O((n+m)logn)

    实际操作中,权值线段树叶子节点维护出现次数,非叶子节点维护子树max值和出现位置,其实也可以只维护max值,统计答案时二分统计

    第一个版本是直接开了1~1e9的权值线段树,常数较大

    #include<iostream>
    #include<cstdio>
    
    using namespace std;
    
    const int MAXN=100005*60;
    
    inline int rd(){
      int ret=0,f=1;char c;
      while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
      while(isdigit(c))ret=ret*10+c-'0',c=getchar();
      return ret*f;
    }
    
    struct Edge{
      int next,to;
    }e[MAXN<<1];
    int ecnt,head[MAXN];
    inline void add(int x,int y){
      e[++ecnt].next = head[x];
      e[ecnt].to = y;
      head[x] = ecnt;
    }
    
    int dep[MAXN],fa[MAXN],hson[MAXN],siz[MAXN];
    void dfs1(int x,int pre){
      dep[x]=dep[pre]+1;fa[x]=pre;siz[x]=1;
      int sz=0;
      for(int i=head[x];i;i=e[i].next){
        int v=e[i].to;
        if(v==pre)continue;
        dfs1(v,x);siz[x]+=siz[v];
        if(siz[v]>sz){sz=siz[v];hson[x]=v;}
      }
    }
    int top[MAXN];
    void dfs2(int x,int tp){
      top[x]=tp;
      if(hson[x])dfs2(hson[x],tp);
      for(int i=head[x];i;i=e[i].next){
          int v=e[i].to;
          if(v==fa[x]||v==hson[x])continue;
          dfs2(v,v);
      }
    }
    int lca(int x,int y){
      while(top[x]!=top[y]){
        dep[top[x]]>=dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
      }
      return dep[x]<=dep[y]?x:y;
    }
    
    int rt[MAXN],num;
    int val[MAXN],mx[MAXN],mxp[MAXN],ch[MAXN][2];
    inline int newnode(){return ++num;}
    inline void pushup(int cur){
      int x=ch[cur][0],y=ch[cur][1];
      int u=mx[x]<mx[y];
      mxp[cur]=mxp[ch[cur][u]];
      mx[cur]=mx[ch[cur][u]];
    }
    void update(int x,int &cur,int l,int r,int w){
      if(!cur)cur=newnode();
      if(l==r){mx[cur]+=w;mxp[cur]=l;return;}
      int mid=(l+r)>>1;
      if(x<=mid)update(x,ch[cur][0],l,mid,w);
      else update(x,ch[cur][1],mid+1,r,w);
      pushup(cur);
    }
    void merge(int &u,int v,int l,int r){
      if(!u||!v) {u=u+v;return;}
      if(l==r){
        mx[u]+=mx[v];
        mxp[u]=l;
        return;
      }
      int mid=(l+r)>>1;
      merge(ch[u][0],ch[v][0],l,mid);
      merge(ch[u][1],ch[v][1],mid+1,r);
      pushup(u);
    }
    int n,m;
    struct Node{
      int x,y,w;
    }a[MAXN];
    int tmp[MAXN],ans[MAXN];
    void dfs(int x){
      for(int i=head[x];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa[x])continue;
        dfs(v);
        merge(rt[x],rt[v],1,1e9);
      }
      ans[x]=mxp[rt[x]];
    }
    int main(){
      n=rd();m=rd();
      int x,y,w;
      for(int i=1;i<n;i++){
        x=rd();y=rd();
        add(x,y);add(y,x);
      }
      dfs1(1,0);dfs2(1,1);
      for(register int i=1;i<=m;i++){
        x=rd();y=rd();tmp[i]=w=rd();
        update(w,rt[x],1,1e9,1);
        update(w,rt[y],1,1e9,1);
        int l=lca(x,y);
        update(w,rt[l],1,1e9,-1);
        if(l=fa[l])update(w,rt[l],1,1e9,-1);
      }
      dfs(1);
      for(register int i=1;i<=n;i++){
        printf("%d
    ",ans[i]);
      }
    }
    View Code

    第二个版本先离散化,开一棵1~m的权值线段树,快了一倍qwq

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    
    using namespace std;
    
    const int MAXN=100005;
    const int N=MAXN*60;
    inline int rd(){
      int ret=0,f=1;char c;
      while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
      while(isdigit(c))ret=ret*10+c-'0',c=getchar();
      return ret*f;
    }
    
    struct Edge{
      int next,to;
    }e[MAXN<<1];
    int ecnt,head[MAXN];
    inline void add(int x,int y){
      e[++ecnt].next = head[x];
      e[ecnt].to = y;
      head[x] = ecnt;
    }
    
    int dep[MAXN],fa[MAXN],hson[MAXN],siz[MAXN];
    void dfs1(int x,int pre){
      dep[x]=dep[pre]+1;fa[x]=pre;siz[x]=1;
      int sz=0;
      for(int i=head[x];i;i=e[i].next){
        int v=e[i].to;
        if(v==pre)continue;
        dfs1(v,x);siz[x]+=siz[v];
        if(siz[v]>sz){sz=siz[v];hson[x]=v;}
      }
    }
    int top[MAXN];
    void dfs2(int x,int tp){
      top[x]=tp;
      if(hson[x])dfs2(hson[x],tp);
      for(int i=head[x];i;i=e[i].next){
          int v=e[i].to;
          if(v==fa[x]||v==hson[x])continue;
          dfs2(v,v);
      }
    }
    int lca(int x,int y){
      while(top[x]!=top[y]){
        dep[top[x]]>=dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
      }
      return dep[x]<=dep[y]?x:y;
    }
    
    int rt[MAXN],num;
    int val[N],mx[N],mxp[N],ch[N][2];
    inline int newnode(){return ++num;}
    inline void pushup(int cur){
      int u=mx[ch[cur][0]]<mx[ch[cur][1]];
      mxp[cur]=mxp[ch[cur][u]];
      mx[cur]=mx[ch[cur][u]];
    }
    void update(int x,int &cur,int l,int r,int w){
      if(!cur)cur=newnode();
      if(l==r){mx[cur]+=w;mxp[cur]=l;return;}
      int mid=(l+r)>>1;
      if(x<=mid)update(x,ch[cur][0],l,mid,w);
      else update(x,ch[cur][1],mid+1,r,w);
      pushup(cur);
    }
    void merge(int &u,int v,int l,int r){
      if(!u||!v) {u=u+v;return;}
      if(l==r){
        mx[u]+=mx[v];
        mxp[u]=l;
        return;
      }
      int mid=(l+r)>>1;
      merge(ch[u][0],ch[v][0],l,mid);
      merge(ch[u][1],ch[v][1],mid+1,r);
      pushup(u);
    }
    int n,m,tot;
    int ans[MAXN];
    void dfs(int x){
      for(int i=head[x];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa[x])continue;
        dfs(v);
        merge(rt[x],rt[v],1,tot);
      }
      ans[x]=mxp[rt[x]];
    }
    
    struct Node{
        int x,y,w;
    }a[MAXN];
    int tmp[MAXN];
    int main(){
      n=rd();m=rd();
      int x,y,w;
      for(int i=1;i<n;i++){
        x=rd();y=rd();
        add(x,y);add(y,x);
      }
      dfs1(1,0);dfs2(1,1);
      for(register int i=1;i<=m;i++){
        a[i].x=rd();a[i].y=rd();a[i].w=tmp[i]=rd();
      }
      sort(tmp+1,tmp+1+m);
      tot=unique(tmp+1,tmp+1+m)-tmp-1;
      for(int i=1;i<=m;i++){
          int x=a[i].x,y=a[i].y,w=lower_bound(tmp+1,tmp+1+tot,a[i].w)-tmp; 
        update(w,rt[x],1,tot,1);
        update(w,rt[y],1,tot,1);
        int l=lca(x,y);
        update(w,rt[l],1,tot,-1);
        if(l=fa[l])update(w,rt[l],1,tot,-1);
      }
      dfs(1);
      for(register int i=1;i<=n;i++){
        printf("%d
    ",tmp[ans[i]]);
      }
    }
    View Code
    未经许可,禁止搬运。
  • 相关阅读:
    git如何进行远程分支切换
    js中实现多态
    css选择器中:first-child与:first-of-type的区别
    js实现图片延时加载的原理
    认识AMD、CMD、UMD、CommonJS
    CORS详解
    JS实现继承的五种方式
    jQuery.fn.extend() 函数详解
    Java基础面试题
    Java面试题集
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9641757.html
Copyright © 2020-2023  润新知