• [ZJOI2008]树的统计-树链剖分


    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e6+5;
    #define mid ((l+r)>>1)
    #define left_son root<<1,l,mid
    #define right_son root<<1|1,mid+1,r
    int n,m;
    int e,begin[maxn],next[maxn],to[maxn],w[maxn],a[maxn];
    struct segment_tree{
    	int sum,l,r,mark,maxw;
    }tree[maxn<<2];
    int son[maxn],id[maxn],father[maxn],cnt,deep[maxn],size[maxn],top[maxn],_map[maxn];
    inline void add(int x,int y){
    	to[++e] = y;
    	next[e] = begin[x];
    	begin[x] = e;
    }
    inline void pushup(int root){
    	tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum;
    	tree[root].maxw = max(tree[root<<1].maxw,tree[root<<1|1].maxw);
    }
    inline void build(int root,int l,int r){
    	tree[root].l = l;
    	tree[root].r = r;
    	tree[root].mark = 0;
    	if(l == r){
    		tree[root].sum = w[_map[l]];
    		tree[root].maxw = w[_map[l]];
    		return;
    	}
    	build(left_son);
    	build(right_son);
    	pushup(root);
    }
    inline void update(int root,int l,int r,int num,int k){
    	if(l == r){
    		tree[root].sum = k;
    		tree[root].maxw = k;
    		return;
    	}
    	if(num <= mid)update(left_son,num,k);
    	else update(right_son,num,k);
    	pushup(root);
    }
    inline int query(int root,int l,int r,int al,int ar){
    	if(al > r || ar < l)return 0;
    	if(al <= l && ar >= r)return tree[root].sum;
    	return query(left_son,al,ar)+query(right_son,al,ar);
    }
    inline int query_max_node(int root,int l,int r,int al,int ar){
    	if(al > r || ar < l)return -999999999;
    	if(al <= l && ar >= r)return tree[root].maxw;
    	return max(query_max_node(left_son,al,ar),query_max_node(right_son,al,ar));
    }
    inline int query_range(int x,int y){
    	int ans = 0;
    	while(top[x] != top[y]){
    		if(deep[top[x]] < deep[top[y]])swap(x,y);
    		ans += query(1,1,cnt,id[top[x]],id[x]);
    		x = father[top[x]];
    	}
    	if(deep[x] > deep[y])swap(x,y);
    	ans += query(1,1,cnt,id[x],id[y]);
    	return ans;
    }
    inline int query_max_range(int x,int y){
    	int ans = -999999999;
    	while(top[x] != top[y]){
    		if(deep[top[x]] < deep[top[y]])swap(x,y);
    		ans = max(ans,query_max_node(1,1,cnt,id[top[x]],id[x]));
    		x = father[top[x]];
    	}
    	if(deep[x] > deep[y])swap(x,y);
    	ans = max(ans,query_max_node(1,1,cnt,id[x],id[y]));
    	return ans;
    }
    inline void dfs1(int x,int fa,int dep){
    	deep[x] = dep;
    	father[x] = fa;
    	size[x] = 1;
    	int maxson = -999999999;
    	for(int i = begin[x];i;i = next[i]){
    		int y = to[i];
    		if(y == fa)continue;
    		dfs1(y,x,dep+1);
    		size[x] += size[y];
    		if(size[y] > maxson)son[x] = y,maxson = size[y];
    	}
    }
    inline void dfs2(int x,int ntop){
    	id[x] = ++cnt;
    	top[x] = ntop;
    	_map[id[x]] = x;
    	if(!son[x])return;
    	dfs2(son[x],ntop);
    	for(int i = begin[x];i;i = next[i]){
    		int y = to[i];
    		if(y == father[x] || y == son[x])continue;
    		dfs2(y,y);
    	}
    }
    int main(){
    	cin>>n;
    	for(int i = 1,u,v;i < n;i++){
    		scanf("%d%d",&u,&v);
    		add(u,v);
    		add(v,u);
    	}
    	for(int i = 1;i <= n;i++)scanf("%d",&w[i]);
    	dfs1(1,0,1);
    	dfs2(1,1);
    	build(1,1,n);
    	cin>>m;
    	while(m--){
    		string ask;
    		int u,v;
    		cin>>ask>>u>>v;
    		if(ask == "CHANGE")update(1,1,cnt,id[u],v);
    		if(ask == "QMAX")printf("%d
    ",query_max_range(u,v));
    		if(ask == "QSUM")printf("%d
    ",query_range(u,v));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    项目管理理论与实践(6)——利用Excel制作项目文档的设计技巧
    项目管理理论与实践(5)——UML应用(下)
    【工具推荐】ELMAH——可插拔错误日志工具
    ExtJs实践(1)——Ext.extend的用法
    设计一套基于NHibernate二级缓存的MongoDB组件(上)
    ExtJs实践(3)——xtype名称与控件对应
    项目管理理论与实践(2)——软件需求分析
    【培训稿件】构建WCF面向服务的应用程序(包含ppt,源代码)
    ExtJs实践(5)——解决在GridPanel中使用bbar或者tbar的分页条的宽度自适应问题
    项目管理理论与实践(3)——如何进行有效的项目管理
  • 原文地址:https://www.cnblogs.com/wangyifan124/p/10298125.html
Copyright © 2020-2023  润新知