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));
    	}
    }
    
  • 相关阅读:
    Android开发笔记——WebView
    字符串_最小表示法求循环串的最小序列(HDU_4162)
    STL_map简单应用(HDU_1075)
    DP_最大子序列和(HDU_1003)
    STL map 使用方法(转)
    数学_线性筛法建立素数表(HDU_1262)
    學習筆記 ADO數據庫訪問技術
    C#多线程学习
    Java容器
    选取单元格的基本语句
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039351.html
Copyright © 2011-2022 走看看