zoukankan      html  css  js  c++  java
  • Luogu P3258 松鼠的新家(树链剖分+线段树/树状数组)

    题面

    题解

      这种题目一看就是重链剖分裸题,还是区间修改,单点查询,查询之前在遍历时要记一个$delta$,因为这一次的起点就是上一次的终点,不需要放糖,所以可以用$BIT$来写,但我写完$modify$才反应过来,所以没改了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using std::swap;
    
    const int N = 3e5 + 10;
    int n, a[N], siz[N], son[N], fa[N], dep[N];
    int tim, dfn[N], top[N], delta[N];
    int cnt, from[N], to[N << 1], nxt[N << 1];
    int val[N << 2], add[N << 2];
    inline void addEdge(int u, int v) {
    	to[++cnt] = v, nxt[cnt] = from[u], from[u] = cnt;
    }
    
    void dfs(int u) {
    	siz[u] = 1, dep[u] = dep[fa[u]] + 1;
    	for(int i = from[u]; i; i = nxt[i]) {
    		int v = to[i]; if(v == fa[u]) continue;
    		fa[v] = u, dfs(v), siz[u] += siz[v];
    		if(siz[v] > siz[son[u]]) son[u] = v;
    	}
    }
    void dfs(int u, int t) {
    	dfn[u] = ++tim, top[u] = t;
    	if(!son[u]) return ; dfs(son[u], t);
    	for(int i = from[u]; i; i = nxt[i]) {
    		int v = to[i];
    		if(v != fa[u] && v != son[u]) dfs(v, v);
    	}
    }
    
    inline void pushup (int o, int lc, int rc) { val[o] = val[lc] + val[rc]; }
    inline void pushdown (int o, int lc, int rc, int len) {
    	if(add[o]) {
    		val[lc] += add[o] * (len - (len >> 1));
    		val[rc] += add[o] * (len >> 1);
    		add[lc] += add[o], add[rc] += add[o], add[o] = 0;
    	}
    }
    void modify (int ml, int mr, int k, int o = 1, int l = 1, int r = n) {
    	if(l >= ml && r <= mr) { val[o] += k * (r - l + 1), add[o] += k; return ; }
    	int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1; 
    	pushdown(o, lc, rc, r - l + 1); 
    	if(ml <= mid) modify(ml, mr, k, lc, l, mid);
    	if(mr > mid) modify(ml, mr, k, rc, mid + 1, r);
    	pushup(o, lc, rc);
    }
    int query(int qs, int o = 1, int l = 1, int r = n) {
    	if(l == r && l == qs) return val[o];
    	int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1; 
    	pushdown(o, lc, rc, r - l + 1); 
    	if(qs <= mid) return query(qs, lc, l, mid);
    	else return query(qs, rc, mid + 1, r);
    }
    
    inline void Path(int x, int y) {
    	int fx = top[x], fy = top[y];
    	while(fx != fy) {
    		if(dep[fx] >= dep[fy]) modify(dfn[fx], dfn[x], 1), x = fa[fx], fx = top[x];
    		else modify(dfn[fy], dfn[y], 1), y = fa[fy], fy = top[y];
    	} if(dfn[x] > dfn[y]) swap(x, y); modify(dfn[x], dfn[y], 1);
    }
    
    int main () {
    	scanf("%d", &n);
    	for(int i = 1; i <= n; ++i) scanf("%d", a + i);
    	for(int i = 1, u, v; i < n; ++i) {
    		scanf("%d%d", &u, &v);
    		addEdge(u, v), addEdge(v, u);
    	}
    	dfs(1), dfs(1, 1);
    	for(int i = 2; i <= n; ++i)
    		Path(a[i - 1], a[i]), ++delta[a[i]];
    	for(int i = 1; i <= n; ++i)
    		printf("%d
    ", query(dfn[i]) - delta[i]);
    	return 0;
    }
    
  • 相关阅读:
    VS2015中SharedProject与可移植类库(PCL)项目
    Windows.Web.Http.HttpClient.GetStringAsync 总是返回相同的结果
    博客园新闻WP8.1客户端
    Webpack 2 视频教程 001
    快速零配置迁移 API 适配 iOS 对 IPv6 以及 HTTPS 的要求
    免费的 Vue.js 入门与进阶视频教程
    Webpack 3 中的新特性
    使用可视化图表对 Webpack 2 的编译与打包进行统计分析
    React.js 开发参见问题 Q&A
    官方 React 快速上手脚手架 create-react-app
  • 原文地址:https://www.cnblogs.com/water-mi/p/9901335.html
Copyright © 2011-2022 走看看