zoukankan      html  css  js  c++  java
  • BZOJ 2157: 旅游 (树链剖分+线段树)

    树链剖分后线段树维护区间最大最小值与和. 支持单点修改与区间取反.

    直接写个区间取反标记就行了.线段树板题.(200行6000B+ 1A警告)

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    inline void read(int &num) {
    	char ch; int flg=1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
    	for(num=0; isdigit(ch); num=num*10+ch-'0',ch=getchar()); num*=flg;
    }
    const int MAXN = 100005;
    const int INF = 1e9;
    
    int n, m, cnt, tmr, bel[MAXN], a[MAXN], w[MAXN], fir[MAXN], fa[MAXN], dfn[MAXN], top[MAXN], sz[MAXN], son[MAXN], dep[MAXN];
    struct edge { int to, nxt, w, id; }e[MAXN<<1];
    inline void Add(int u, int v, int wt, int i) {
    	e[cnt] = (edge){ v, fir[u], wt, i }, fir[u] = cnt++;
    	e[cnt] = (edge){ u, fir[v], wt, i }, fir[v] = cnt++;
    }
    void dfs(int x) {
    	dep[x] = dep[fa[x]] + (sz[x]=1);
    	for(int v, i = fir[x]; ~i; i = e[i].nxt)
    		if((v=e[i].to) != fa[x]) {
    			fa[v] = x, a[v] = e[i].w;
    			bel[e[i].id] = v;
    			dfs(v), sz[x] += sz[v];
    			if(sz[v] > sz[son[x]]) son[x] = v;
    		}
    }
    void dfs2(int x, int tp) {
    	top[x] = tp; w[dfn[x] = ++tmr] = a[x];
    	if(son[x]) dfs2(son[x], tp);
    	for(int v, i = fir[x]; ~i; i = e[i].nxt)
    		if((v=e[i].to) != fa[x] && v != son[x])
    			dfs2(v, v);
    }
    
    namespace SegmentTree {
    	int sum[MAXN<<2], mx[MAXN<<2], mn[MAXN<<2];
    	bool rev[MAXN<<2];
    	inline void update(int i) {
    		sum[i] = sum[i<<1] + sum[i<<1|1];
    		mx[i] = max(mx[i<<1], mx[i<<1|1]);
    		mn[i] = min(mn[i<<1], mn[i<<1|1]);
    	}
    	inline void pushdown(int i) {
    		if(rev[i]) {
    			rev[i] ^= 1, rev[i<<1] ^= 1, rev[i<<1|1] ^= 1;
    			sum[i<<1] *= -1, sum[i<<1|1] *= -1;
    			swap(mx[i<<1], mn[i<<1]);
    			mx[i<<1] *= -1, mn[i<<1] *= -1;
    			swap(mx[i<<1|1], mn[i<<1|1]);
    			mx[i<<1|1] *= -1, mn[i<<1|1] *= -1;
    			rev[i] = 0;
    		}
    	}
    	void build(int i, int l, int r) {
    		if(l == r) {
    			mx[i] = mn[i] = sum[i] = w[l];
    			return;
    		}
    		int mid = (l + r) >> 1;
    		build(i<<1, l, mid);
    		build(i<<1|1, mid+1, r);
    		update(i);
    	}
    	void modify(int i, int l, int r, int x, int y) {
    		if(l == r) {
    			mx[i] = mn[i] = sum[i] = y;
    			return;
    		}
    		pushdown(i);
    		int mid = (l + r) >> 1;
    		if(x <= mid) modify(i<<1, l, mid, x, y);
    		else modify(i<<1|1, mid+1, r, x, y);
    		update(i);
    	}
    	void cover(int i, int l, int r, int x, int y) {
    		if(l == x && r == y) {
    			rev[i] ^= 1;
    			sum[i] *= -1;
    			swap(mx[i], mn[i]);
    			mx[i] *= -1, mn[i] *= -1;
    			return;
    		}
    		pushdown(i);
    		int mid = (l + r) >> 1;
    		if(y <= mid) cover(i<<1, l, mid, x, y);
    		else if(x > mid) cover(i<<1|1, mid+1, r, x, y);
    		else cover(i<<1, l, mid, x, mid), cover(i<<1|1, mid+1, r, mid+1, y);
    		update(i);
    	}
    	int querysum(int i, int l, int r, int x, int y) {
    		if(l == x && r == y) return sum[i];
    		pushdown(i);
    		int mid = (l + r) >> 1, res = 0;
    		if(y <= mid) res = querysum(i<<1, l, mid, x, y);
    		else if(x > mid) res = querysum(i<<1|1, mid+1, r, x, y);
    		else res = querysum(i<<1, l, mid, x, mid) + querysum(i<<1|1, mid+1, r, mid+1, y);
    		update(i);
    		return res;
    	}
    	int querymx(int i, int l, int r, int x, int y) {
    		if(l == x && r == y) return mx[i];
    		pushdown(i);
    		int mid = (l + r) >> 1, res = -INF;
    		if(y <= mid) res = querymx(i<<1, l, mid, x, y);
    		else if(x > mid) res = querymx(i<<1|1, mid+1, r, x, y);
    		else res = max(querymx(i<<1, l, mid, x, mid), querymx(i<<1|1, mid+1, r, mid+1, y));
    		update(i);
    		return res;
    	}
    	int querymn(int i, int l, int r, int x, int y) {
    		if(l == x && r == y) return mn[i];
    		pushdown(i);
    		int mid = (l + r) >> 1, res = INF;
    		if(y <= mid) res = querymn(i<<1, l, mid, x, y);
    		else if(x > mid) res = querymn(i<<1|1, mid+1, r, x, y);
    		else res = min(querymn(i<<1, l, mid, x, mid), querymn(i<<1|1, mid+1, r, mid+1, y));
    		update(i);
    		return res;
    	}
    }
    
    inline void Invert(int x, int y) {
    	while(top[x] != top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		SegmentTree::cover(1, 1, n, dfn[top[x]], dfn[x]);
    		x = fa[top[x]];
    	}
    	if(x == y) return;
    	if(dep[x] < dep[y]) swap(x, y);
    	SegmentTree::cover(1, 1, n, dfn[y]+1, dfn[x]);
    }
    
    inline int Sum(int x, int y) {
    	int res = 0;
    	while(top[x] != top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		res += SegmentTree::querysum(1, 1, n, dfn[top[x]], dfn[x]);
    		x = fa[top[x]];
    	}
    	if(x == y) return res;
    	if(dep[x] < dep[y]) swap(x, y);
    	res += SegmentTree::querysum(1, 1, n, dfn[y]+1, dfn[x]);
    	return res;
    }
    
    inline int Max(int x, int y) {
    	int res = -INF;
    	while(top[x] != top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		res = max(res, SegmentTree::querymx(1, 1, n, dfn[top[x]], dfn[x]));
    		x = fa[top[x]];
    	}
    	if(x == y) return res;
    	if(dep[x] < dep[y]) swap(x, y);
    	res = max(res, SegmentTree::querymx(1, 1, n, dfn[y]+1, dfn[x]));
    	return res;
    }
    
    inline int Min(int x, int y) {
    	int res = INF;
    	while(top[x] != top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		res = min(res, SegmentTree::querymn(1, 1, n, dfn[top[x]], dfn[x]));
    		x = fa[top[x]];
    	}
    	if(x == y) return res;
    	if(dep[x] < dep[y]) swap(x, y);
    	res = min(res, SegmentTree::querymn(1, 1, n, dfn[y]+1, dfn[x]));
    	return res;
    }
    
    int main() {
    	memset(fir, -1, sizeof fir);
    	read(n);
    	for(int x, y, z, i = 1; i < n; ++i)
    		read(x), read(y), read(z), Add(x+1, y+1, z, i);
    	dfs(1); dfs2(1, 1);
    	SegmentTree::build(1, 1, n);
    	read(m);
    	int x, y; char s[2];
    	while(m--) {
    		while(!isalpha(s[0]=getchar())); s[1] = getchar();
    		read(x), read(y);
    		if(s[0] == 'S') printf("%d
    ", Sum(x+1, y+1));
    		else if(s[0] == 'M' && s[1] == 'A') printf("%d
    ", Max(x+1, y+1));
    		else if(s[0] == 'M' && s[1] == 'I') printf("%d
    ", Min(x+1, y+1));
    		else if(s[0] == 'C') SegmentTree::modify(1, 1, n, dfn[bel[x]], y);
    		else Invert(x+1, y+1);
    	}
    }
    
  • 相关阅读:
    Vue动画操作
    js this
    flask 操作mysql的两种方式-sqlalchemy操作
    flask 操作mysql的两种方式-sql操作
    ansible批量加用户
    使用 WTForms 进行表单验证的例子
    flask开发用户管理系统wtf版
    [转]Python格式化输出
    scrapy中response.body 与 response.text区别
    flask开发表单
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039353.html
Copyright © 2011-2022 走看看