• bzoj 3307: 雨天的尾巴 线段树合并


    题目大意:

    N个点,形成一个树状结构。有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。问完成所有发放后,每个点存放最多的是哪种物品。

    题解:

    首先我们为每一个节点都开一个线段树
    然后我们进行树上路径差分:
    对于一个从u->v的路径,我们将其分解为:
    u->1 , v->1,fa[lca(u,v)] -> 1
    lca表示最近公共祖先,fa[x]为x的父亲节点
    所以我们需要附加权值
    我们可以在u的线段树上加上1
    在v的线段树上加上1
    在lca(u,v)的线段树上加上-1
    在fa[lca(u,v)]的线段树上加上-1
    然后我们自叶子向根依次进行线段树的合并即可

    Code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
    inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
    const int maxn = 110010;
    const int inf = 0x3f3f3f3f;
    struct Edge{
    	int to,next;
    }G[maxn<<1];
    int head[maxn],cnt;
    void add(int u,int v){
    	G[++cnt].to = v;
    	G[cnt].next = head[u];
    	head[u] = cnt;
    }
    #define v G[i].to
    int siz[maxn],son[maxn],fa[maxn],dep[maxn];
    int top[maxn];
    void dfs(int u){
    	siz[u] = 1;
    	for(int i = head[u];i;i=G[i].next){
    		if(v == fa[u]) continue;
    		dep[v] = dep[u] + 1;
    		fa[v] = u;
    		dfs(v);
    		siz[u] += siz[v];
    		if(siz[son[u]] < siz[v]) son[u] = v;
    	}
    }
    void dfs(int u,int tp){
    	top[u] = tp;
    	if(son[u]) dfs(son[u],tp);
    	for(int i = head[u];i;i=G[i].next){
    		if(v == fa[u] || v == son[u]) continue;
    		dfs(v,v);
    	}
    }
    #undef v
    inline int lca(int u,int v){
    	while(top[u] != top[v]){
    		if(dep[top[u]] < dep[top[v]]) swap(u,v);
    		u = fa[top[u]];
    	}return dep[u] < dep[v] ? u : v;
    }
    struct Node{
    	Node *ch[2];
    	int mx,id;
    	void update();
    }*null;
    void Node::update(){
    	mx = max(ch[0]->mx,ch[1]->mx);
    	if(mx == ch[0]->mx) id = ch[0]->id;
    	else if(mx == ch[1]->mx) id = ch[1]->id;
    }
    Node mem[maxn<<6],*it;
    inline void init(){
    	it = mem;null = it++;
    	null->ch[0] = null->ch[1] = null;
    	null->mx = -inf;null->id = -1;
    }
    inline Node* newNode(){
    	Node *p = it++;p->ch[0] = p->ch[1] = null;
    	p->mx = -inf;p->id = 0;return p;
    }
    void merge(Node* &x,Node *y){
    	if(x == null){x = y;return;}
    	if(x->ch[0] == null || y->ch[0] == null){
    		x->ch[0] = y->ch[0] == null ? x->ch[0] : y->ch[0];
    	}else merge(x->ch[0],y->ch[0]);
    	if(x->ch[1] == null || y->ch[1] == null){
    		x->ch[1] = y->ch[1] == null ? x->ch[1] : y->ch[1];
    	}else merge(x->ch[1],y->ch[1]);
    	if(x->ch[0] == x->ch[1] && x->ch[0] == null){
    		x->mx += y->mx;
    	}else x->update();
    	return;
    }
    void insert(Node* &p,int l,int r,int pos,int d){
    	if(p == null) p = newNode();
    	if(l == r){
    		p->id = pos;
    		if(p->mx == -inf) p->mx = d;
    		else p->mx += d;
    		return;
    	}
    	int mid = (l+r) >> 1;
    	if(pos <= mid) insert(p->ch[0],l,mid,pos,d);
    	else insert(p->ch[1],mid+1,r,pos,d);
    	p->update();return;
    }
    Node *root[maxn];
    int anss[maxn];
    #define v G[i].to
    void dfss(int u,int fa){
    	for(int i = head[u];i;i=G[i].next){
    		if(v == fa) continue;
    		dfss(v,u);
    		merge(root[u],root[v]);
    	}
    	if(root[u]->id != -1) anss[u] = root[u]->id;
    }
    #undef v
    int main(){
    	init();
    	int n,m;read(n);read(m);
    	for(int i=0;i<=n;++i) root[i] = null;
    	for(int i=1,u,v;i<n;++i){
    		read(u);read(v);
    		add(u,v);add(v,u);
    	}dfs(1);dfs(1,1);
    	for(int i=1,u,v,d;i<=m;++i){
    		read(u);read(v);read(d);
    		insert(root[u],1,1e9,d,1);
    		insert(root[v],1,1e9,d,1);
    		int lc = lca(u,v);
    		insert(root[lc],1,1e9,d,-1);
    		if(lc != 1) insert(root[fa[lc]],1,1e9,d,-1);
    	}dfss(1,0);
    	for(int i=1;i<=n;++i){
    		printf("%d
    ",anss[i]);
    	}
    	getchar();getchar();
    	return 0;
    }
    
  • 相关阅读:
    bzoj1914
    bzoj3144
    bzoj2756
    poj3177
    一些比较水的题目
    bzoj2282
    屯题50AC纪念
    Base64解码中文部分中文乱码的原因
    随机生成36位字符串
    jQuery判断某个元素是否存在某个样式
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6445993.html
Copyright © 2020-2023  润新知