zoukankan      html  css  js  c++  java
  • UOJ58 【WC2013】糖果公园

    UOJ58 【WC2013】糖果公园

    蒟蒻学个树上莫队都要学一晚上

    树上莫队是依照dfs序的,将不过在点遍历完所有儿子后还要再进行一次打时间戳。

    用这种方法,再特判一下LCA就好了。

    网上的大多数方法都是将树进行分块,也比较简单。

    #include <bits/stdc++.h>
    #define N 100003
    #define wlp while
    #define rep(i, l, r) for (int i = l; i <= r; ++i)
    #define FOR(a, b) for (edge *a = g[b]; a; a = a->n)
    inline void gi(int &x) {
    	static char c;
    	wlp (c = getchar(), c < '0'); x = c - '0';
    	wlp (c = getchar(), '-' < c) x = (x << 3) + (x << 1) + c - '0';
    }
    struct edge {int t; edge *n;} me[N<<1|1], *g[N], *ce = me;
    #define adde(a, b) (ce->t = b, ce->n = g[a], g[a] = ce++)
    struct quy{int x, y, t, id, lca;} Q[N];
    struct chg{int x, y, pre;} P[N];
    int in[N], ou[N], son[N], fa[N], tp[N], dep[N], dfn, _Q, _P, bel[N<<1|1], block, que[N<<1|1];
    int V[N], W[N], C[N], col[N], cnt[N]; long long ANS[N], ans;
    bool mark[N];
    bool operator < (const quy &a, const quy &b) {
    	
    	if (bel[a.x] ^ bel[b.x]) return bel[a.x] < bel[b.x];
    	if (bel[a.y] ^ bel[b.y]) return bel[a.y] < bel[b.y];
    	return a.t < b.t;
    	
    	//return bel[a.x]==bel[b.x]?(bel[a.y]==bel[b.y]?a.t<b.t:bel[a.y]<bel[b.y]):bel[a.x]<bel[b.x];
    }
    int d1(int u, int f) {
    	int r = 1, mx = -1, t;
    	dep[u] = dep[f] + 1;
    	fa[u] = f;
    	FOR(it, u) if (it->t ^ f) {
    		t = d1(it->t, u);
    		if (t > mx) mx = t, son[u] = it->t;
    		r += t;
    	}
    	return r;
    }
    void d2(int u, int anc) {
    	que[in[u] = ++dfn] = u;
    	tp[u] = anc;
    	if (son[u]) d2(son[u], anc);
    	FOR(it, u) if (!tp[it->t]) d2(it->t, it->t);
    	que[ou[u] = ++dfn] = u;
    }
    inline int LCA(int u, int v) {
    	wlp (tp[u] ^ tp[v]) dep[tp[u]] < dep[tp[v]] ? v = fa[tp[v]] : u = fa[tp[u]];
    	return dep[u] < dep[v] ? u : v;
    }
    inline void rev(const int &u) {
    	if (mark[u]) ans -= (long long)V[C[u]] * W[cnt[C[u]]--];
    	else ans += (long long)V[C[u]] * W[++cnt[C[u]]];
    	mark[u] ^= 1;
    }
    inline void upd(const int &u, const int &nc) {
    	if (mark[u]) rev(u), C[u] = nc, rev(u);
    	else C[u] = nc;
    }
    inline void timetravel(int &ct, const int &target) {
    	wlp (ct < target) ++ct, upd(P[ct].x, P[ct].y);
    	wlp (target < ct) upd(P[ct].x, P[ct].pre), --ct;
    }
    int main() {
    	//freopen("58.in", "r", stdin);
    	//freopen("58.out", "w", stdout);
    	int n, m, q, x, y, ct, type, l, r, _l, _r;
    	gi(n), gi(m), gi(q);
    	rep(i, 1, m) gi(V[i]);
    	rep(i, 1, n) gi(W[i]);
    	rep(i, 2, n) {
    		gi(x), gi(y);
    		adde(x, y);
    		adde(y, x);
    	}
    	rep(i, 1, n) gi(C[i]), col[i] = C[i];
    	d1(n, 0); d2(n, n);
    	block = pow(dfn, 2.0 / 3) * 0.5 + 1e-3;
    	if (!block) block = 1;
    	rep(i, 1, dfn) bel[i] = (i - 1) / block;
    	rep(i, 1, q)
    		if (gi(type), gi(x), gi(y), type) {
    			ct = LCA(x, y);
    			if (in[y] < in[x]) std::swap(x, y);
    			if (ct ^ x) Q[_Q] = (quy) {ou[x], in[y], _P, _Q, ct};
    			else Q[_Q] = (quy) {in[x], in[y], _P, _Q, 0};
    			++_Q;
    		} else {
    			P[++_P] = (chg) {x, y, col[x]};
    			col[x] = y;
    		}
    	std::sort(Q, Q + _Q);
    	l = 1, r = 0, ct = 0;
    	for (int i = 0; i < _Q; ++i) {
    		_l = Q[i].x, _r = Q[i].y;
    		timetravel(ct, Q[i].t);
    		wlp (l < _l) rev(que[l++]);
    		wlp (l > _l) rev(que[--l]);
    		wlp (r < _r) rev(que[++r]);
    		wlp (r > _r) rev(que[r--]);
    		if (Q[i].lca) rev(Q[i].lca);
    		ANS[Q[i].id] = ans;
    		if (Q[i].lca) rev(Q[i].lca);
    	}
    	for (int i = 0; i < _Q; ++i) printf("%lld
    ", ANS[i]);
    	return 0;
    }
    
  • 相关阅读:
    4.再来看看逆向——OD的简介
    3.资源里加个混淆
    反编译python打包的exe文件
    2.释放资源那些事
    1.恶意软件中的防双开
    windbg源码驱动调试 + 无源码驱动调试
    [转]当勒索病毒“不图财”时会图什么?
    勒索病毒加密过程分析1——简易加密型(坏兔子病毒)
    通过驱动杀死那个进程
    前端学习笔记 day14 模拟滚动条
  • 原文地址:https://www.cnblogs.com/cycleke/p/6380508.html
Copyright © 2011-2022 走看看