zoukankan      html  css  js  c++  java
  • CF757G Can Bash Save the Day?【边分树】

    给定 (n) 个点的树(边带权)和长为 (n) 的排列 (a)(q) 次操作 ( exttt{1 l r v}) 询问 (sum_{i=l}^r ext{dis}(a_i,v))( exttt{2 x}) 表示 swap(a[x],a[x+1])。强制在线。

    (n,qleq 2cdot 10^5)


    可持久化边分树。。。

    行,叫我练 DS 我就写!

    本质上是边分树合并,类似线段树合并,边分树的结构本身是确定的,维护的是每个节点的信息。

    建立 (n) 棵边分树,第 (i) 棵表示 (a_1,a_2,cdots,a_i) 的信息,查询就差分一下,拆成 (sum_{i=1}^r ext{dis}(a_i,v)),枚举 lca 计算贡献,修改就重构第 (x) 棵边分树。

    预处理的时候边分树不需完整建出来,只需对每个点处理出其在每一层是左儿子还是右儿子,以及到分治中心的距离。

    时空复杂度 (O((n+q)log n))

    #include<bits/stdc++.h>
    #include<vector>
    #define PB emplace_back
    #define fi first
    #define se second
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    const int N = 200003, M = N*70, B = (1<<30)-1;
    template<typename T>
    void rd(T &x){
    	int ch = getchar(); x = 0;
    	for(;ch < '0' || ch > '9';ch = getchar());
    	for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
    }
    template<typename T>
    bool chmax(T &a, const T &b){if(a < b) return a = b, 1; return 0;}
    int n, q, nc, p[N], head[N<<1], to[N<<2], nxt[N<<2], we[N<<2];
    vector<pii> G[N];
    void add(int a, int b, int c){
    	static int cnt = 1;
    	to[++cnt] = b; nxt[cnt] = head[a]; head[a] = cnt; we[cnt] = c;
    	to[++cnt] = a; nxt[cnt] = head[b]; head[b] = cnt; we[cnt] = c;
    }
    void reb(int x, int fa){
    	for(auto it = G[x].begin();it != G[x].end();++ it)
    		if(it->fi == fa){G[x].erase(it); break;}
    	for(pii _ : G[x]) reb(_.fi, x);
    	while(G[x].size() > 2){
    		pii _ = G[x].back(); G[x].pop_back();
    		add(++nc, _.fi, _.se);
    		_ = G[x].back(); G[x].pop_back();
    		add(nc, _.fi, _.se);
    		G[x].PB(nc, 0);
    	}
    	for(pii _ : G[x]) add(x, _.fi, _.se);
    }
    int all, tmp, rte, siz[N<<1], dep[N];
    bool vis[N<<2], opt[N][23];
    LL dis0[N][23], dis1[N][23];
    void fdrt(int x, int fa){
    	siz[x] = 1;
    	for(int i = head[x], v;i;i = nxt[i]){
    		if(vis[i] || (v = to[i]) == fa) continue;
    		fdrt(v, x); siz[x] += siz[v];
    		if(chmax(tmp, min(siz[v], all-siz[v])))
    			rte = i;
    	}
    }
    void calc(int x, int fa, LL dis, int d, bool op){
    	if(x <= n){
    		opt[x][d] = op;
    		dis0[x][d] = dis;
    		dis1[x][d] = dis+we[rte];
    	}
    	for(int i = head[x];i;i = nxt[i])
    		if(!vis[i] && to[i] != fa)
    			calc(to[i], x, dis+we[i], d, op);
    }
    void dac(int x, int d, int S){
    	if(S <= 1){
    		if(x <= n) dep[x] = d; return;
    	} all = S; tmp = 0; fdrt(x, 0);
    	int u = to[rte], v = to[rte^1];
    	vis[rte] = vis[rte^1] = true;
    	calc(u, v, 0, d, 0);
    	calc(v, u, 0, d, 1);
    	dac(v, d+1, S-siz[u]);
    	dac(u, d+1, siz[u]);
    }
    int tot, rt[N], ls[M], rs[M], ct[M][2];
    LL sm[M][2], lans;
    void merg(int &x, int y, int d, int u){
    	if(d >= dep[u]) return;
    	x = ++tot;
    	ls[x] = ls[y]; rs[x] = rs[y];
    	ct[x][0] = ct[y][0]; ct[x][1] = ct[y][1];
    	sm[x][0] = sm[y][0]; sm[x][1] = sm[y][1];
    	bool op = opt[u][d];
    	sm[x][op] += dis0[u][d]; ++ct[x][op];
    	if(op) merg(rs[x], rs[y], d+1, u);
    	else merg(ls[x], ls[y], d+1, u);
    }
    void qry(int x, int y, int d, int u){
    	if(d >= dep[u]) return;
    	bool op = opt[u][d];
    	lans += sm[y][!op] - sm[x][!op] + dis1[u][d]*(ct[y][!op]-ct[x][!op]);
    	if(op) qry(rs[x], rs[y], d+1, u);
    	else qry(ls[x], ls[y], d+1, u);
    }
    int main(){
    	rd(n); rd(q); nc = n; 
    	for(int i = 1;i <= n;++ i) rd(p[i]);
    	for(int i = 1, u, v, w;i < n;++ i){
    		rd(u); rd(v); rd(w);
    		G[u].PB(v, w); G[v].PB(u, w);
    	} reb(1, 0); dac(1, 0, nc);
    	for(int i = 1;i <= n;++ i)
    		merg(rt[i], rt[i-1], 0, p[i]);
    	while(q --){
    		int op, l, r, x; rd(op);
    		if(op == 1){
    			rd(l); rd(r); rd(x);
    			l ^= lans; r ^= lans; x ^= lans;
    			lans = 0; qry(rt[l-1], rt[r], 0, x);
    			printf("%lld
    ", lans); lans &= B;
    		} else {
    			rd(x); x ^= lans; swap(p[x], p[x+1]);
    			merg(rt[x], rt[x-1], 0, p[x]);
    		}
    	}
    }
    
  • 相关阅读:
    最短路径 Floyd && spfa
    queue 优先队列
    POJ Wormholes 最短路径 ballman_ ford 有负环
    上帝造题五分钟
    算法提高 新建Microsoft Word文档
    算法训练 最短路
    Ubuntu14 Could not open file /var/lib/dpkg/status
    MongoDB权威指南<2> 1-1 MongoDB 介绍
    SaltStack Char03 实践案例
    ELK Stack
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/14912220.html
Copyright © 2011-2022 走看看