【线段树 树链剖分 差分 经典技巧】loj#3046. 「ZJOI2019」语言【未完】
还是来致敬一下那过往吧
题目分析
先丢代码
1 #include<bits/stdc++.h> 2 const int maxn = 100035; 3 const int maxm = 200035; 4 const int maxNode = 20000035; 5 6 struct node 7 { 8 int top,son,fa,tot; 9 }a[maxn]; 10 struct point 11 { 12 int u,v; 13 point(int a=0, int b=0):u(a),v(b) {} 14 }; 15 struct tree 16 { 17 int ls,rs,cov,val; 18 }f[maxNode]; 19 int n,m,tot; 20 long long ans,det; 21 int chain[maxn],chTot,rt[maxn]; 22 int edgeTot,head[maxn],edges[maxm],nxt[maxm],dep[maxn]; 23 std::vector<point> opt[maxn]; 24 std::vector<int> inc[maxn],dec[maxn]; 25 26 int read() 27 { 28 char ch = getchar(); 29 int num = 0, fl = 1; 30 for (; !isdigit(ch); ch=getchar()) 31 if (ch=='-') fl = -1; 32 for (; isdigit(ch); ch=getchar()) 33 num = (num<<1)+(num<<3)+ch-48; 34 return num*fl; 35 } 36 void addedge(int u, int v) 37 { 38 edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot; 39 edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot; 40 } 41 void dfs1(int x, int fa) 42 { 43 dep[x] = dep[fa]+1, a[x].tot = 1; 44 a[x].top = a[x].son = -1, a[x].fa = fa; 45 for (int i=head[x]; i!=-1; i=nxt[i]) 46 { 47 int v = edges[i]; 48 if (v==fa) continue; 49 dfs1(v, x), a[x].tot += a[v].tot; 50 if (a[x].son==-1||a[a[x].son].tot < a[v].tot) 51 a[x].son = v; 52 } 53 } 54 void dfs2(int x, int top) 55 { 56 a[x].top = top, chain[x] = ++chTot; 57 if (a[x].son==-1) return; 58 dfs2(a[x].son, top); 59 for (int i=head[x]; i!=-1; i=nxt[i]) 60 if (edges[i]!=a[x].fa&&edges[i]!=a[x].son) 61 dfs2(edges[i], edges[i]); 62 } 63 void splitChain(int id, int u, int v) 64 { 65 inc[u].push_back(id), inc[v].push_back(id); 66 while (a[u].top!=a[v].top) 67 { 68 if (dep[a[u].top] > dep[a[v].top]) std::swap(u, v); 69 opt[id].push_back(point(chain[a[v].top], chain[v])); 70 v = a[a[v].top].fa; 71 } 72 if (dep[u] > dep[v]) std::swap(u, v); 73 opt[id].push_back(point(chain[u], chain[v])); 74 dec[u].push_back(id), dec[a[u].fa].push_back(id); 75 } 76 void pushup(int rt, int len) 77 { 78 if (f[rt].cov) f[rt].val = len; 79 else f[rt].val = f[f[rt].ls].val+f[f[rt].rs].val; 80 } 81 void mergeSeg(int &u, int v, int l, int r) 82 { 83 if (!u||!v) u += v; 84 else{ 85 int mid = (l+r)>>1; 86 f[u].cov += f[v].cov; 87 mergeSeg(f[u].ls, f[v].ls, l, mid); 88 mergeSeg(f[u].rs, f[v].rs, mid+1, r); 89 } 90 pushup(u, r-l+1); 91 } 92 void update(int &rt, int L, int R, int l, int r, int c) 93 { 94 if (!rt) rt = ++tot; 95 if (L <= l&&r <= R) f[rt].cov += c, pushup(rt, r-l+1); 96 else{ 97 int mid = (l+r)>>1; 98 if (L <= mid) update(f[rt].ls, L, R, l, mid, c); 99 if (R > mid) update(f[rt].rs, L, R, mid+1, r, c); 100 } 101 pushup(rt, r-l+1); 102 } 103 void delta(int x, int fa) 104 { 105 for (int i=head[x]; i!=-1; i=nxt[i]) 106 if (edges[i]!=fa) delta(edges[i], x); 107 for (int l=0; l<inc[x].size(); l++) 108 for (int i=0,mx=opt[inc[x][l]].size(); i<mx; i++) 109 update(rt[x], opt[inc[x][l]][i].u, opt[inc[x][l]][i].v, 1, n, 1); 110 for (int l=0; l<dec[x].size(); l++) 111 for (int i=0,mx=opt[dec[x][l]].size(); i<mx; i++) 112 update(rt[x], opt[dec[x][l]][i].u, opt[dec[x][l]][i].v, 1, n, -1); 113 int val = f[rt[x]].val; 114 if (val) ans += val, ++det; 115 mergeSeg(rt[fa], rt[x], 1, n); 116 } 117 int main() 118 { 119 memset(head, -1, sizeof head); 120 n = read(), m = read(); 121 for (int i=1; i<n; i++) 122 addedge(read(), read()); 123 dfs1(1, 0), dfs2(1, 1); 124 for (int i=1; i<=m; i++) 125 splitChain(i, read(), read()); 126 delta(1, 0); 127 printf("%lld\n",(ans-det)/2); 128 return 0; 129 }