• 6813. 【2020.10.05提高组模拟】送信


    真的是我第一次打不是板题的三维偏序。。。
    打得我精疲力尽要死要活。。。

    (Solution)

    我们尝试将树上问题转化成一个平面内的问题。我们先按时间排序。
    对于添加一个点对,我们可以看成在((dfn[x])$ed[x],dfn[y]$(ed[y]))这个矩阵当中加(1)
    到时候查询的时候只需要查询两个点((dfn[x],dfn[y]))((dfn[y],dfn[x]))即可。
    而对于矩阵加(1)可以分成两个不同(x)(+1)(-1),相当于差分。
    我们只需要在(CDQ)分治的时候搞成(x)排序的即可。
    然后在分治后处理合并问题的时候左区间做修改,右区间查询即可。
    用一个数据结构来维护一下(y)坐标的答案值即可。

    有一点小细节需要注意:
    对于添加一个矩阵([x1)$x2,y1$(y2]),我们分成的是(x1)的和(x2+1)的。
    对于当前区间中只有某次操作的(-1),而这次操作的(+1)在左边的区间内的话。
    由于到时候合并的时候右边区间的操作不需要进行修改,所以到时候还是会加回去的,值不变。

    (Code)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 400010
    #define ll long long
    #define lowbit(x) (x & (-x))
    #define mem(x, a) memset(x, a, sizeof x)
    #define mpy(x, y) memcpy(x, y, sizeof y)
    #define fo(x, a, b) for (int x = (a); x <= (b); x++)
    #define fd(x, a, b) for (int x = (a); x >= (b); x--)
    #define go(x) for (int p = tail[x], v; p; p = e[p].fr)
    using namespace std;
    struct ask{int ti, x, yl, yr, pl;}q[N << 2], c[N << 2];
    struct node{int v, fr;}e[N << 1];
    int n, m, Q, tail[N], cnt = 0, fa[N][17], aw[N];
    int ord[N], dfn[N], ed[N], tot = 0, dep[N], hav_ans = 1;
    int t[N];
    
    inline int read() {
    	int x = 0, f = 0; char c = getchar();
    	while (c < '0' || c > '9') f = (c == '-') ? 1 : f, c = getchar();
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f ? -x : x;
    }
    
    inline void add(int u, int v) {e[++cnt] = (node){v, tail[u]}; tail[u] = cnt;}
    
    void dfs(int x) {
    	for (int i = 0; fa[fa[x][i]][i]; i++)
    		fa[x][i + 1] = fa[fa[x][i]][i];
    	dfn[++tot] = x, ord[x] = tot;
    	go(x) {
    		if ((v = e[p].v) == fa[x][0]) continue;
    		dep[v] = dep[x] + 1, fa[v][0] = x, dfs(v);
    	}
    	ed[x] = tot;
    }
    
    int calc_(int x, int y) {
    	if (dep[x] < dep[y]) swap(x, y);
    	fd(i, 16, 0) if (dep[x] - (1 << i) > dep[y]) x = fa[x][i];
    	return x;
    }
    
    void modify(int x, int pl) {for (int i = x; i <= n; i += lowbit(i)) t[i] += pl;}
    
    int query(int x) {int s = 0; for (int i = x; i; i -= lowbit(i)) s += t[i]; return s;} 
    
    void CDQ(int l, int r) {
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	CDQ(l, mid), CDQ(mid + 1, r);
    	int le = l, ri = mid + 1, now_ = l;
    //	fo(i, 1, n) t[i] = 0;
    	while (now_ <= r) {
    		if (le <= mid && (ri > r || q[le].x <= q[ri].x)) {
    			c[now_] = q[le], now_++;
    			if (q[le].pl != 1 && q[le].pl != -1) {le++; continue;}
    			modify(q[le].yl, q[le].pl), modify(q[le].yr + 1, -q[le].pl), le++;
    		}
    		else {
    			c[now_] = q[ri], now_++;
    			if (q[ri].pl == 1 || q[ri].pl == -1) {ri++; continue;}
    			aw[q[ri].pl] += query(q[ri].yr); ri++;
    		}
    	}
    	fo(i, l, mid) {
    		if (q[i].pl != 1 && q[i].pl != -1) continue;
    		modify(q[i].yl, -q[i].pl), modify(q[i].yr + 1, q[i].pl);
    	}
    	fo(i, l, r) q[i] = c[i];
    	return;
    } 
    
    int main()
    {
    	freopen("letter.in", "r", stdin);
    	freopen("letter.out", "w", stdout);
    	n = read(), m = read(), Q = read();
    	fo(i, 2, n) {
    		int u = read(), v = read();
    		add(u, v), add(v, u);
    	}
    	dfs(1); tot = 0;
    	fo(i, 1, m) {
    		int x = read(), y = read(), nd = calc_(x, y);
    		if (ord[x] > ord[y]) swap(x, y);
    		if (fa[nd][0] == x) {
    			q[++tot] = (ask){1, 1, ord[y], ed[y], +1};
    			q[++tot] = (ask){1, ord[nd], ord[y], ed[y], -1};
    			q[++tot] = (ask){1, ed[nd] + 1, ord[y], ed[y], +1};
    			q[++tot] = (ask){1, n + 1, ord[y], ed[y], -1};
    		}
    		else {
    			q[++tot] = (ask){1, ord[x], ord[y], ed[y], +1};
    			q[++tot] = (ask){1, ed[x] + 1, ord[y], ed[y], -1};
    		}
    	}
    	fo(i, 1, Q) {
    		int opt = read(), x = read(), y = read();
    		if (ord[x] > ord[y]) swap(x, y);
    		if (opt == 1) {
    			q[++tot] = (ask){i + 1, ord[x], ord[y], ord[y], ++hav_ans};
    			q[++tot] = (ask){i + 1, ord[y], ord[x], ord[x], hav_ans};
    		}
    		else {
    			int nd = calc_(x, y);
    			if (fa[nd][0] == x) {
    				q[++tot] = (ask){i + 1, 1, ord[y], ed[y], +1};
    				q[++tot] = (ask){i + 1, ord[nd], ord[y], ed[y], -1};
    				q[++tot] = (ask){i + 1, ed[nd] + 1, ord[y], ed[y], +1};
    				q[++tot] = (ask){i + 1, n + 1, ord[y], ed[y], -1};
    			}
    			else {
    				q[++tot] = (ask){i + 1, ord[x], ord[y], ed[y], +1};
    				q[++tot] = (ask){i + 1, ed[x] + 1, ord[y], ed[y], -1};
    			}
    		}
    	}
    	/*
    	fo(i, 1, tot) printf("%d %d %d %d
    ", q[i].x, q[i].yl, q[i].yr, q[i].pl);
    	return 0;
    	*/
    	CDQ(1, tot);
    	fo(i, 2, hav_ans) printf("%d
    ", aw[i]);
    	return 0;
    }
    
  • 相关阅读:
    洛谷 P2607 [ZJOI2008]骑士(基环树、树形dp)
    洛谷 P1453 城市环路(基环树,树形dp)
    基环树学习笔记 & CF711D Directed Roads
    centos7 系统安全加固方案
    来自后端的突袭? --开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor
    作为一个C#程序员, 你应该上手Kotlin
    python中类和self讲解
    Mysql 存储引擎中InnoDB与Myisam的主要区别
    Apache和Nginx的区别
    PHP超全局变量
  • 原文地址:https://www.cnblogs.com/jz929/p/13807752.html
Copyright © 2020-2023  润新知