zoukankan      html  css  js  c++  java
  • [树链剖分]

    [BZOJ 3531][SDOI 2014]旅行

    动态开点线段树+树剖。

    写完 编译 一遍过样例 交了 1A 这感觉还挺爽QAQ。。

    #include <bits/stdc++.h>
    #define maxn 100010
    using namespace std;
    
    int n, Q;
    int w[maxn], c[maxn];
    //-------------------------------------------------------------------//
    struct Edge{
    	int to, next;
    }edge[maxn << 1];
    int h[maxn], cnt;
    void add(int u, int v){
    	cnt ++;
    	edge[cnt].to = v;
    	edge[cnt].next = h[u];
    	h[u] = cnt;
    }
    //-------------------------------------------------------------------//
    int son[maxn], top[maxn], pos[maxn], dfs_clock, size[maxn];
    int fa[maxn], dep[maxn];
    
    void dfs1(int u){
    	dep[u] = dep[fa[u]] + 1;
    	size[u] = 1;
    	for(int i = h[u]; i; i = edge[i].next){
    		int v = edge[i].to;
    		if(v == fa[u])continue;
    		fa[v] = u;
    		dfs1(v);
    		size[u] += size[v];
    		if(size[v] > size[son[u]])
    		    son[u] = v;
    	}
    }
    
    void dfs2(int u, int tp){
    	pos[u] = ++ dfs_clock;
    	top[u] = tp;
    	if(son[u])dfs2(son[u], tp);
    	for(int i = h[u]; i; i = edge[i].next){
    		int v = edge[i].to;
    		if(v == fa[u] || v == son[u])
    		    continue;
    		dfs2(v, v);
    	}
    }
    
    //-------------------------------------------------------------------//
    
    #define M 10000010
    int root[maxn], lc[M], rc[M], mx[M], s[M], Smz;
    
    void pushup(int id){
    	s[id] = s[lc[id]] + s[rc[id]];
    	mx[id] = max(mx[lc[id]], mx[rc[id]]);
    }
    
    void update(int &id, int l, int r, int p, int val){
    	if(id == 0)id = ++ Smz;
    	if(l == r){s[id] = val, mx[id] = val;return;}
    	int mid = l + r >> 1;
    	if(p <= mid)update(lc[id], l, mid, p, val);
    	else update(rc[id], mid+1, r, p, val);
    	pushup(id);
    }
    
    int Asksum(int id, int l, int r, int L, int R){
    	if(id == 0)return 0;
    	if(l == L && R == r)return s[id];
    	int mid = l + r >> 1;
    	if(R <= mid)return Asksum(lc[id], l, mid, L, R);
    	if(L > mid) return Asksum(rc[id], mid+1, r, L, R);
    	return Asksum(lc[id], l, mid, L, mid) + Asksum(rc[id], mid+1, r, mid+1, R);
    }
    
    int Askmx(int id, int l, int r, int L, int R){
    	if(id == 0)return 0;
    	if(l == L && R == r)return mx[id];
    	int mid = l + r >> 1;
    	if(R <= mid)return Askmx(lc[id], l, mid, L, R);
    	if(L > mid) return Askmx(rc[id], mid+1, r, L, R);
    	return max(Askmx(lc[id], l, mid, L, mid), Askmx(rc[id], mid+1, r, mid+1, R));
    }
    
    int asksum(int u, int v){
    	int C = c[u], ret = 0;
    	while(top[u] != top[v]){
    		if(dep[top[u]] < dep[top[v]])
    		    swap(u, v);
    		ret += Asksum(root[C], 1, n, pos[top[u]], pos[u]);
    		u = fa[top[u]];
    	}
    	if(dep[u] > dep[v])swap(u, v);
    	ret += Asksum(root[C], 1, n, pos[u], pos[v]);
    	return ret;
    }
    
    int askmx(int u, int v){
        int C = c[u], ret = 0;
    	while(top[u] != top[v]){
    		if(dep[top[u]] < dep[top[v]])
    		    swap(u, v);
    		ret = max(ret, Askmx(root[C], 1, n, pos[top[u]], pos[u]));
    		u = fa[top[u]];
    	}
    	if(dep[u] > dep[v])swap(u, v);
    	ret = max(ret, Askmx(root[C], 1, n, pos[u], pos[v]));
    	return ret;
    }
    
    int main(){
    	char cmd[2];
    	scanf("%d%d", &n, &Q);
    	for(int i = 1; i <= n; i ++)
    	    scanf("%d%d", &w[i], &c[i]);
    	int x, y;
    	for(int i = 1; i < n; i ++){
    		scanf("%d%d", &x, &y);
    		add(x, y), add(y, x);
    	}
    	
    	dfs1(1);
    	dfs2(1, 1);
    	for(int i = 1; i <= n; i ++)
    		update(root[c[i]], 1, n, pos[i], w[i]);
    	
    	while(Q --){
    		scanf("%s", cmd);
    		scanf("%d%d", &x, &y);
    		switch(cmd[1]){
    			case 'C':
                    update(root[c[x]], 1, n, pos[x], 0), c[x] = y;
                    update(root[y], 1, n, pos[x], w[x]);
    				break;
    			case 'W':
    				update(root[c[x]], 1, n, pos[x], w[x] = y);
    				break;
    			case 'S':
    				printf("%d
    ", asksum(x, y));
    				break;
    			case 'M':
                    printf("%d
    ", askmx(x, y));
    				break;
    		}
    	}
    	return 0;
    }
    
    给时光以生命,而不是给生命以时光。
  • 相关阅读:
    Mini2440裸机开发之MMU
    Mini2440裸机开发之IIC
    Mini2440裸机开发之SPI
    Mini2440裸机开发之存储器控制器
    Mini2440裸机开发之模数转换开发
    Mini2440裸机开发之LCD编程(GB2312、ASCII字库制作)
    Python pandas df.iloc[:, 0] 取确定列值作双轴图
    python plot 画双坐标轴 设置百分比展示 和字体等细节
    python Sqlserver数据库画双轴图
    windows下Idea中用Python访问oracle数据库的方法
  • 原文地址:https://www.cnblogs.com/Candyouth/p/5413788.html
Copyright © 2011-2022 走看看