zoukankan      html  css  js  c++  java
  • CF600E Lomsat gelral 【线段树合并】

    题目链接

    CF600E

    题解

    容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可
    对于每个节点合并一下两个子节点的信息
    要注意叶子节点信息的合并和非叶节点信息的合并是不一样的

    由于合并不比逐个插入复杂度高,所以应是(O(nlogn))

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 100005,maxm = 8000005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    LL sum[maxm],ans[maxn];
    int ls[maxm],rs[maxm],mx[maxm],cnt;
    int n,c[maxn],fa[maxn],rt[maxn];
    int h[maxn],ne = 1;
    struct EDGE{int to,nxt;}ed[maxn << 1];
    inline void build(int u,int v){
    	ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
    	ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
    }
    inline void upd(int u){
    	sum[u] = 0;
    	if (mx[ls[u]] >= mx[rs[u]]){
    		mx[u] = mx[ls[u]];
    		sum[u] += sum[ls[u]];
    	}
    	if (mx[rs[u]] >= mx[ls[u]]){
    		mx[u] = mx[rs[u]];
    		sum[u] += sum[rs[u]];
    	}
    }
    void modify(int& u,int pre,int l,int r,int pos){
    	u = ++cnt; ls[u] = ls[pre]; rs[u] = rs[pre];
    	if (l == r){mx[u] = mx[pre] + 1; sum[u] = l; return;}
    	int mid = l + r >> 1;
    	if (mid >= pos) modify(ls[u],ls[pre],l,mid,pos);
    	else modify(rs[u],rs[pre],mid + 1,r,pos);
    	upd(u);
    }
    int merge(int u,int v,int l,int r){
    	if (!u) return v;
    	if (!v) return u;
    	int t = ++cnt,mid = l + r >> 1;
    	if (l == r){
    		mx[t] = mx[u] + mx[v];
    		sum[t] = l;
    		return t;
    	}
    	ls[t] = merge(ls[u],ls[v],l,mid);
    	rs[t] = merge(rs[u],rs[v],mid + 1,r);
    	upd(t);
    	return t;
    }
    void dfs(int u){
    	modify(rt[u],rt[u],1,n,c[u]);
    	Redge(u) if ((to = ed[k].to) != fa[u]){
    		fa[to] = u; dfs(to);
    		rt[u] = merge(rt[u],rt[to],1,n);
    	}
    	ans[u] = sum[rt[u]];
    }
    int main(){
    	n = read();
    	REP(i,n) c[i] = read();
    	for (int i = 1; i < n; i++) build(read(),read());
    	dfs(1);
    	REP(i,n) printf("%lld ",ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    UVA 10600 ACM Contest and Blackout(次小生成树)
    UVA 10369
    UVA Live 6437 Power Plant 最小生成树
    UVA 1151 Buy or Build MST(最小生成树)
    UVA 1395 Slim Span 最小生成树
    POJ 1679 The Unique MST 次小生成树
    POJ 1789 Truck History 最小生成树
    POJ 1258 Agri-Net 最小生成树
    ubuntu 用法
    ubuntu 搭建ftp服务器,可以通过浏览器访问,filezilla上传文件等功能
  • 原文地址:https://www.cnblogs.com/Mychael/p/9210792.html
Copyright © 2011-2022 走看看