zoukankan      html  css  js  c++  java
  • codeforces 600E 线段树合并

      题意:给你一棵有 nn 个点的树 (nleq10^5)(n105) ,树上每个节点都有一种颜色 ci(cileq n)ci(cin) ,让你求每个点子树出现最多的颜色的 颜色编号 的和

    线段树合并可以维护子树的所有线段树之和 

    权值线段维护一下出现最多的数字即可

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    const int N=2e6+10;
    
    ll sum[N<<2],t[N<<2],anss[N];
    int lson[N<<2],rson[N<<2],ncnt,pos,head[N],c[N],n,T[N];
    
    void up(int pos)
    {
        if(sum[lson[pos]]>sum[rson[pos]])
        {
            sum[pos]=sum[lson[pos]];
            t[pos]=t[lson[pos]];
        }
        else if(sum[lson[pos]]<sum[rson[pos]])
        {
            sum[pos]=sum[rson[pos]];
            t[pos]=t[rson[pos]];
        }
        else if(sum[lson[pos]]==sum[rson[pos]])
        {
            sum[pos]=sum[lson[pos]];
            t[pos]=t[lson[pos]]+t[rson[pos]];
        }
    }
    
    void upnode(int x,int l,int r,int &pos)
    {
        if(!pos)pos=++ncnt;
        if(l==r){sum[pos]+=1;t[pos]=l;return ;}
        int m=(l+r)>>1;
        if(x<=m)upnode(x,l,m,lson[pos]);
        else upnode(x,m+1,r,rson[pos]);
        up(pos);
    }
    int Merge(int a,int b,int l,int r)
    {
        if(!a)return b;
        if(!b)return a;
        if(l==r)
        {
            sum[a]+=sum[b];
            t[a]=l;
            return a;
        }
        int m=(l+r)>>1;
        lson[a]=Merge(lson[a],lson[b],l,m);
        rson[a]=Merge(rson[a],rson[b],m+1,r);
        up(a);return a;
    }
    
    struct Edge{int to,nex;}edge[N];
    void add(int a,int b){edge[++pos]=(Edge){b,head[a]};head[a]=pos;}
    
    void dfs(int x,int fa)
    {
        for(int i=head[x];i;i=edge[i].nex)
        {
            int v=edge[i].to;
            if(v==fa)continue;
            dfs(v,x);//注意 这里是 先更新 然后再合并
            Merge(T[x],T[v],1,1e5);
        }
        upnode(c[x],1,100000,T[x]);
        anss[x]=t[T[x]];
    }
    
    int main()
    {
        cin>>n;
        rep(i,1,n)scanf("%d",&c[i]),ncnt++,T[i]=i;
        rep(i,1,n-1)
        {
            int x,y;scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
    
        }
        dfs(1,0);
        rep(i,1,n)
        printf("%lld ",anss[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    background-size属性的几个实用的值
    用jQuery实现旋转木马效果(带前后按钮和索引按钮)
    用jQuery制作仿网易云课堂导航菜单效果
    IE8专用hack
    jQuery的slicebox插件实现3D翻转轮播效果
    未知宽高的图片水平垂直居中的几种方法
    清除浮动的几种方法
    用canvas实现鼠标拖动绘制矩形框
    个人收藏的移动端网页布局rem解决方案
    jQuery仿3D旋转木马效果插件(带索引按钮)
  • 原文地址:https://www.cnblogs.com/bxd123/p/11382564.html
Copyright © 2011-2022 走看看