zoukankan      html  css  js  c++  java
  • BZOJ 3531: [Sdoi2014]旅行 (树剖+动态开点线段树)

    对于每种信仰维护一棵动态开点线段树就行了…

    #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, fir[MAXN], fa[MAXN], dfn[MAXN], top[MAXN], sz[MAXN], son[MAXN], dep[MAXN];
    struct edge { int to, nxt; }e[MAXN<<1];
    inline void Add(int u, int v) {
    	e[cnt] = (edge){ v, fir[u] }, fir[u] = 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, dfs(v), sz[x] += sz[v];
    			if(sz[v] > sz[son[x]]) son[x] = v;
    		}
    }
    void dfs2(int x, int tp) {
    	top[x] = tp; dfn[x] = ++tmr;
    	if(son[x]) dfs2(son[x], tp);
    	for(int v, i = fir[x]; ~i; i = e[i].nxt)
    		if((v=e[i].to) != son[x] && v != fa[x]) dfs2(v, v);
    }
    
    namespace SegmentTree {
    	struct seg {
    		seg *ls, *rs;
    		int mx, sum;
    		inline void* operator new(size_t, seg *_ls, seg *_rs, int _mx, int _sum) {
    			static seg *mempool, *C;
    			if(mempool == C) mempool = (C = new seg[1<<15]) + (1<<15);
    			C->ls = _ls;
    			C->rs = _rs;
    			C->mx = _mx;
    			C->sum = _sum;
    			return C++;
    		}
    	}*rt[MAXN];
    	inline void update(seg *x) {
    		x->mx = x->sum = 0;
    		if(x->ls) x->mx = max(x->mx, x->ls->mx), x->sum += x->ls->sum;
    		if(x->rs) x->mx = max(x->mx, x->rs->mx), x->sum += x->rs->sum;
    	}
    	void insert(seg *&x, int l, int r, int pos, int val) {
    		if(!x) x = new(0x0, 0x0, 0, 0) seg;
    		if(l == r) {
    			x->sum = x->mx = val;
    			return;
    		}
    		int mid = (l + r) >> 1;
    		if(pos <= mid) insert(x->ls, l, mid, pos, val);
    		else insert(x->rs, mid+1, r, pos, val);
    		update(x);
    	}
    	int querysum(seg *p, int l, int r, int x, int y) {
    		if(!p) return 0;
    		if(l == x && r == y) return p->sum;
    		int mid = (l + r) >> 1;
    		if(y <= mid) return querysum(p->ls, l, mid, x, y);
    		else if(x > mid) return querysum(p->rs, mid+1, r, x, y);
    		else return querysum(p->ls, l, mid, x, mid) + querysum(p->rs, mid+1, r, mid+1, y);
    	}
    	int querymx(seg *p, int l, int r, int x, int y) {
    		if(!p) return 0;
    		if(l == x && r == y) return p->mx;
    		int mid = (l + r) >> 1;
    		if(y <= mid) return querymx(p->ls, l, mid, x, y);
    		else if(x > mid) return querymx(p->rs, mid+1, r, x, y);
    		else return max(querymx(p->ls, l, mid, x, mid), querymx(p->rs, mid+1, r, mid+1, y));
    	}
    }
    inline int Sum(SegmentTree::seg *r, 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(r, 1, n, dfn[top[x]], dfn[x]);
    		x = fa[top[x]];
    	}
    	if(dep[x] < dep[y]) swap(x, y);
    	res += SegmentTree::querysum(r, 1, n, dfn[y], dfn[x]);
    	return res;
    }
    inline int Max(SegmentTree::seg *r, int x, int y) {
    	int res = 0;
    	while(top[x] != top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		res = max(res, SegmentTree::querymx(r, 1, n, dfn[top[x]], dfn[x]));
    		x = fa[top[x]];
    	}
    	if(dep[x] < dep[y]) swap(x, y);
    	res = max(res, SegmentTree::querymx(r, 1, n, dfn[y], dfn[x]));
    	return res;
    }
    int c[MAXN], w[MAXN];
    int main() {
    	memset(fir, -1, sizeof fir);
    	read(n), read(m);
    	for(int i = 1; i <= n; ++i) read(w[i]), read(c[i]);
    	for(int x, y, i = 1; i < n; ++i) {
    		read(x), read(y);
    		Add(x, y), Add(y, x);
    	}
    	dfs(1); dfs2(1, 1);
    	for(int i = 1; i <= n; ++i) SegmentTree::insert(SegmentTree::rt[c[i]], 1, n, dfn[i], w[i]);
    	int x, y; char s[2];
    	while(m--) {
    		while(!isalpha(s[0] = getchar())); s[1] = getchar();
    		read(x), read(y);
    		if(s[0] == 'C' && s[1] == 'W') SegmentTree::insert(SegmentTree::rt[c[x]], 1, n, dfn[x], w[x]=y);
    		else if(s[0] == 'C' && s[1] == 'C') SegmentTree::insert(SegmentTree::rt[c[x]], 1, n, dfn[x], 0), c[x] = y, SegmentTree::insert(SegmentTree::rt[c[x]], 1, n, dfn[x], w[x]);
    		else if(s[0] == 'Q' && s[1] == 'S') printf("%d
    ", Sum(SegmentTree::rt[c[x]], x, y));
    		else printf("%d
    ", Max(SegmentTree::rt[c[x]], x, y));
    	}
    }
    
  • 相关阅读:
    leetcode 190 Reverse Bits
    vs2010 单文档MFC 通过加载位图文件作为客户区背景
    leetcode 198 House Robber
    记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence
    逆序数2 HDOJ 1394 Minimum Inversion Number
    矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence
    递推DP URAL 1586 Threeprime Numbers
    递推DP URAL 1167 Bicolored Horses
    递推DP URAL 1017 Staircases
    01背包 URAL 1073 Square Country
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039351.html
Copyright © 2011-2022 走看看