http://www.lydsy.com/JudgeOnline/problem.php?id=3757 (Topic link)
MD tune for a long time, finally quine a few standard way to turn, did not expect all re ... Finally, we see:
= =
Test instructions: How many different points on the path between two points on a tree?
Solution
Like this tree chain can not solve the problem, probably is the tree on the Mo team.
We dfs to the tree block, this is very simple, will not see bzoj1086. After the query (U,V) with the position of the block where U is the first keyword, the Dfs order for V is the second keyword. In fact, this does not help us to deal with the problem, but to ensure that the complexity of the team is NSQRTN, because the size of each block is sqrt (n), the number of blocks is also sqrt (n), so that the DFS sequence for the second keyword after ordering in each block to modify, Worst case is the whole tree, O (n).
How to insert delete and solve it? Quine a god, but there is a formula phobia I looked at a few eyes do not want to see, direct grinding the standard go.
Use S (V, U) to represent the set of nodes on the path of V to U.
Use root to represent the root node and use LCA (V, U) to represent the nearest public ancestor of V and U.
So
S (V, u) = s (root, V) XOR s (Root, U) Xor LCA (V, u)
Where XOR is the symmetric difference of the set.
In simple terms, nodes appear to disappear two times.
LCA is very annoying, and then define
T (V, u) = s (root, V) XOR s (Root, u)
Observe the changes in T (CURV, Curu) before and after moving CURV to Targetv:
T (CURV, Curu) = s (root, CURV) XOR s (Root, Curu)
T (Targetv, Curu) = s (root, Targetv) XOR s (Root, Curu)
Symmetry difference:
T (CURV, Curu) XOR T (Targetv, Curu) = (s (root, CURV) XOR s (Root, Curu)) Xor (S (Root, Targetv) XOR s (Root, Curu))
Due to the commutative law of the symmetry difference, the binding law:
T (CURV, Curu) XOR T (Targetv, Curu) = S (root, Curv) xors (root, Targetv)
Both sides simultaneously XOR T (CURV, Curu):
T (Targetv, Curu) = t (curv, Curu) XOR s (Root, CURV) XOR s (Root, Targetv)
Found the last two very cool ... Wow, haha.
T (Targetv, Curu) = t (curv, Curu) XOR T (CURV, TARGETV)
(There is a formula phobia don't go ah t_t)
In other words, when updating, Xor T (CURV, Targetv) is on the line.
That is, the CURV to Targetv path (excluding LCA (CURV, Targetv)) on the nodes, the existence of them can be reversed.
”
--VFK Blog
Having done so much, the truth is simple. For a query, using the array p[i] record color I in the current query has appeared several times; vis[i] Record node I has been counted, if already counted, then is to delete the current node, and vice versa is to join the current node, by the way to update the answer ans can.
Code I don't know if it's right = =
Code:
bzoj3757#include<algorithm> #include <iostream> #include <cstring> #include <cstdlib># include<cstdio> #include <cmath> #define MOD 1000000007#define inf 2147483640#define LL long long#define Free (a) Freopen (a ". In", "R", stdin); Freopen (a ". Out", "w", stdout); using namespace Std;inline ll Getint () {ll X=0,f=1;char ch=g Etchar (); while (ch> ' 9 ' | | ch< ' 0 ') {if (ch== '-') F=-1;ch=getchar ();} while (ch>= ' 0 ' && ch<= ' 9 ') {x=x*10+ch-' 0 '; Ch=getchar ();} return x*f;} const int maxn=100010;struct Edge {int to,next;} E[maxn<<2];struct ask {int u,v,a,b,id;} T[maxn];int cnt,n,q,m,block,top,ans;int Head[maxn],dfn[maxn],fa[maxn][20],bin[20],deep[maxn],p[maxn];int ST[MAXN] , pos[maxn],vis[maxn],c[maxn],a[maxn],res[maxn];void Insert (int u,int v) {E[++cnt].to=v;e[cnt].next=head[u];head[u] =cnt; e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;} int dfs (int x) {dfn[x]=++cnt; int size=0; for (int i=1;i<20;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for (int i=head[x];i;i=e[i].next) if (E[i].to!=fa[x][0]) {deep[e[i].to]=deep[x]+1; Fa[e[i].to][0]=x; Size+=dfs (e[i].to); if (size>=block) {m++; for (int j=1;j<=size;j++) pos[st[top--]]=m; size=0; }} st[++top]=x; return size+1;} BOOL CMP (ask A,ask b) {return pos[a.u]==pos[b.u]? DFN[A.V]<DFN[B.V]: pos[a.u]<pos[b.u];} int LCA (int x,int y) {if (Deep[x]<deep[y]) swap (x, y); int t=deep[x]-deep[y]; for (int i=0;bin[i]<=t;i++) if (bin[i]&t) x=fa[x][i]; for (int i=19;i>=0;i--) if (Fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return x==y?x:fa[x][0];} void work (int x) {if (!vis[x]) {vis[x]=1;p[c[x]]++;if (p[c[x]]==1) ans++;} else {vis[x]=0;p[c[x]]--;if (p[c[x]]==0) ans--;}} void Solve (int u,int v) {while (u!=v) {if (Deep[u]>deep[v]) Work (U), u=fa[u][0]; else Work (v), v=fa[v][0]; }}int Main () {bin[0]=1;for (int i=1;i<20;i++) bin[i]=bin[i-1]<<1; scanf ("%d%d", &n,&q); for (int i=1;i<=n;i++) scanf ("%d", &c[i]); for (int i=1;i<=n;i++) {int u,v; scanf ("%d%d", &u,&v); Insert (U,V); } block= (int) sqrt (n); cnt=0; DFS (E[HEAD[0]].TO); m++; while (top) pos[st[top--]]=m; for (int i=1;i<=q;i++) {scanf ("%d%d%d%d", &t[i].u,&t[i].v,&t[i].a,&t[i].b); if (DFN[T[I].U]>DFN[T[I].V]) swap (T[I].U,T[I].V); T[i].id=i; } sort (t+1,t+1+q,cmp); Solve (T[1].U,T[1].V); int X=lca (T[1].U,T[1].V); Work (x); Res[t[1].id]=ans; if (P[T[1].A] && p[t[1].b] && t[1].a!=t[1].b) res[t[1].id]--; Work (x); for (int i=2;i<=q;i++) {solve (T[I-1].U,T[I].U); Solve (T[I-1].V,T[I].V); X=lca (T[I].U,T[I].V); Work (x); if (P[T[I].A] && p[t[i].b] && t[i].a!=t[i].b) res[t[i].id]=ans-1; else Res[t[i].id]=ans; Work (x); } for (int i=1;i<=q;i++) printf ("%d\n", Res[i]); return 0;}
"Bzoj3757" apple tree