• BZOJ 2836: 魔法树 (树链剖分+线段树)


    板题…记得开longlong

    #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];
    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) {
    		fa[v=e[i].to] = 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]) dfs2(v, v);
    }
    
    namespace SegmentTree {
    	LL sum[MAXN<<2], lz[MAXN<<2]; int l[MAXN<<2], r[MAXN<<2];
    	inline void update(int i) {
    		sum[i] = sum[i<<1] + sum[i<<1|1];
    	}
    	inline void pushdown(int i) {
    		if(lz[i]) {
    			lz[i<<1] += lz[i], lz[i<<1|1] += lz[i];
    			sum[i<<1] += lz[i] * (r[i<<1] - l[i<<1] + 1);
    			sum[i<<1|1] += lz[i] * (r[i<<1|1] - l[i<<1|1] + 1);
    			lz[i] = 0;
    		}
    	}
    	void build(int i, int x, int y) {
    		l[i] = x, r[i] = y;
    		if(x == y) return;
    		int mid = (x + y) >> 1;
    		build(i<<1, x, mid);
    		build(i<<1|1, mid+1, y);
    	}
    	void insert(int i, int x, int y, int val) {
    		if(l[i] == x && r[i] == y) {
    			sum[i] += val * (y - x + 1);
    			lz[i] += val;
    			return;
    		}
    		pushdown(i);
    		int mid = (l[i] + r[i]) >> 1;
    		if(y <= mid) insert(i<<1, x, y, val);
    		else if(x > mid) insert(i<<1|1, x, y, val);
    		else insert(i<<1, x, mid, val), insert(i<<1|1, mid+1, y, val);
    		update(i);
    	}
    	LL querysum(int i, int x, int y) {
    		if(l[i] == x && r[i] == y) return sum[i];
    		pushdown(i);
    		LL mid = (l[i] + r[i]) >> 1, res = 0;
    		if(y <= mid) res = querysum(i<<1, x, y);
    		else if(x > mid) res = querysum(i<<1|1, x, y);
    		else res = querysum(i<<1, x, mid) + querysum(i<<1|1, mid+1, y);
    		update(i);
    		return res;
    	}
    }
    
    inline void Add(int x, int y, int val) {
    	while(top[x] != top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		SegmentTree::insert(1, dfn[top[x]], dfn[x], val);
    		x = fa[top[x]];
    	}
    	if(dep[x] < dep[y]) swap(x, y);
    	SegmentTree::insert(1, dfn[y], dfn[x], val);
    }
    
    int main() {
    	memset(fir, -1, sizeof fir);
    	read(n);
    	for(int x, y, i = 1; i < n; ++i)
    		read(x), read(y), Add(x+1, y+1);
    	dfs(1); dfs2(1, 1);
    	SegmentTree::build(1, 1, n);
    	read(m);
    	int x, y, z; char s[2];
    	while(m--) {
    		while(!isalpha(s[0]=getchar()));
    		if(s[0] == 'A') read(x), read(y), read(z), Add(x+1, y+1, z);
    		else read(x), printf("%lld
    ", SegmentTree::querysum(1, dfn[x+1], dfn[x+1]+sz[x+1]-1));
    	}
    }
    
  • 相关阅读:
    BZOJ 3218: a + b Problem
    P4542 [ZJOI2011]营救皮卡丘
    P4843 清理雪道
    P4553 80人环游世界
    P4126 [AHOI2009]最小割
    P2619 [国家集训队2]Tree I
    P2469 [SDOI2010]星际竞速
    P2050 [NOI2012]美食节
    易语言入门
    jdbc连接oracle语法
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039352.html
Copyright © 2020-2023  润新知