Summary on the review of tree division and treatment

Source: Internet
Author: User

A few days ago to fill in the pit of the reconstruction plan accidentally found their own tree division has been a place a bit bug, is the wrong qaq (but seems to have little impact

So the King de Yao World, hurriedly went to find a few tree division to practice

The bug is the W array that the sum directly uses when the tree is divided to find the center of gravity, but for each layer of the W array to recalculate (yet I'm not qaq

WC2010 Redevelopment Programme

This is a bug-heavy code, I used 19min finish, hand over 1A

But then I found out there were at least three errors in the code. Qaq the data is too weak.

Stick to a bug-heavy code, and by the way exercise to find bug ability?

The procedure is to-mid each edge after the two-point answer, judging whether there is a path of edge and >=0

#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include < Cstdlib> #define EPS 1e-5using namespace std; const int Maxn=100010;const int Oo=0x7fffffff/3;int n,l,r,tmp;int u,v,b;int mn,mx;double ans,l,r;int h[maxn],cnt=0; struct edge{int to,next,w;} G[maxn<<1];int g,sum;int f[maxn],w[maxn];int son[maxn],tot=0;double fa[maxn];d ouble DEP[MAXN],MX_DEP[MAXN]; int Q[maxn];bool VIS[MAXN]; BOOL CMP (const int &AMP;A,CONST int &b) {return w[a]<w[b];} void Add (int x,int y,int z) {++cnt; G[cnt].to=y; G[CNT].NEXT=H[X]; g[cnt].w=z;h[x]=cnt;}    void read (int &num) {Num=0;char Ch=getchar (); while (ch< '! ')    Ch=getchar (); while (ch>= ' 0 ' &&ch<= ' 9 ') num=num*10+ch-' 0 ', Ch=getchar ();} void Cmax (int &a,int b) {if (b>a) a=b;}    void get_g (int u,int fa) {f[u]=0;w[u]=1;        for (int i=h[u];i;i=g[i].next) {int v=g[i].to; if (vis[v]| |        V==FA) continue;        Get_g (V,u);        W[U]+=W[V];    Cmax (F[u],w[v]); }cMax (F[u],sum-w[u]); if (F[g]>f[u]) g=u;}    void Get_dis (int u,int f,int d,double dis,double k) {if (d>tmp) Tmp=d;    if (Dep[d]<dis) Dep[d]=dis;        for (int i=h[u];i;i=g[i].next) {int v=g[i].to; if (vis[v]| |        V==F) continue;    Get_dis (V,U,D+1,DIS+G[I].W-K,K); }return;}    BOOL Check (int u,double k) {int len=0;tmp=0;    for (int i=1;i<=w[u];++i) Mx_dep[i]=-oo;        for (int i=1;i<=tot;++i) {int v=son[i];tmp=0;        for (int j=1;j<=w[v];++j) Dep[j]=-oo;        Get_dis (V,-1,1,FA[V]-K,K);        int now=0,h=0,t=-1;            for (int j=tmp;j>=1;--j) {if (r-j<0) continue;                while (Now<=r-j&&now<=len) {while (H<=t&&mx_dep[now]>mx_dep[q[t]]) t--;            q[++t]=now;now++;            } while (H<=t&&q[h]<l-j) h++;        if (h<=t&&mx_dep[q[h]]+dep[j]>0) return true;        } if (Tmp>len) len=tmp; for (int i=1;i<=len;++i) Mx_dep[i]=max (mx_dep[I],dep[i]); }return false;}    void Get_ans (int u) {l=ans;r=mx;    tot=0;        for (int i=h[u];i;i=g[i].next) {int v=g[i].to;        if (Vis[v]) continue;    SON[++TOT]=V;FA[V]=G[I].W;    } sort (son+1,son+tot+1,cmp);        while (r-l>eps) {double mid= (l+r)/2.0;        if (check (u,mid)) L=mid;    else R=mid; }ans=l;} void Get_div (int u) {vis[u]=true;    Get_ans (U);        for (int i=h[u];i;i=g[i].next) {int v=g[i].to;        if (Vis[v]) continue;        sum=w[v];g=0; Get_g (v,-1);    Get_div (g); }return;}    int main () {scanf ("%d%d%d", &n,&l,&r);    Mn=oo;mx=-oo;        for (int i=1;i<n;++i) {read (u); Read (v); Read (b);        Add (u,v,b); add (v,u,b);    Mx=max (mx,b); Mn=min (mn,b);    }ANS=MN;    F[0]=oo;g=0;sum=n; Get_g (1,-1);    Get_div (g);    printf ("%.3lf\n", ans); return 0;}

The three bugs I found are:

1, W array is not recalculated (empty MX_DEP and DEP also use the W array, actually no WA)

2, I cycle there is another I cycle

3, before processing no sub-tree sorting, easy to be stuck into O (n^2)

SPOJ free Travel

Show technology forced to write O (NLOGN)

It's the same as rebuilding the plan, but it's a bug-free code.

#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include < cstdlib>using namespace Std;const int maxn=400010;const int oo=0x7fffffff/3;int n,k,m,tmp;int U,v,a;bool BLACK[MAXN] ; bool Vis[maxn];int h[maxn],cnt=0;int ans=0;struct edge{int to,next,w;} G[maxn<<1];int g,sum;int f[maxn],w[maxn],b[maxn];int son[maxn],tot=0;int fa[maxn],Q[maxn];int dep[maxn],mx_ Dep[maxn];bool CMP (const int &AMP;X,CONST int &y) {return b[x]<b[y];} void Add (int x,int y,int z) {++cnt; G[cnt].to=y; G[CNT].NEXT=H[X]; g[cnt].w=z;h[x]=cnt;} void read (int &num) {num=0;int F=1;char Ch=getchar (); while (ch< '! ') Ch=getchar (); if (ch== '-') F=-1,ch=getchar (); while (ch>= ' 0 ' &&ch<= ' 9 ') num=num*10+ch-' 0 ', Ch=getchar (); Num*=f;} void Cmax (int &a,int b) {if (b>a) a=b;} void get_g (int u,int fa) {f[u]=0;w[u]=1;b[u]=black[u];for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]| | V==FA) continue; Get_g (V,u); W[u]+=w[v];b[u]+=b[v];cmax (F[u],w[v]);} Cmax (F[u],sum-w[u]); if (f[g]>f[u]) G=u;} void DFS (int u,int fa) {w[u]=1;b[u]=black[u];for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]| | V==FA) Continue;dfs (v,u); w[u]+=w[v];b[u]+=b[v];} return;} void Get_dis (int u,int f,int d,int dis) {if (d>tmp) tmp=d;if (Dep[d]<dis) dep[d]=dis;for (int i=h[u];i;i=g[i].next) { int V=g[i].to;if (vis[v]| | V==F) continue; Get_dis (V,U,D+BLACK[V],DIS+G[I].W);} return;} void Get_ans (int u) {int len=0,flag=black[u];for (int i=0;i<=b[u];++i) mx_dep[i]=-oo;mx_dep[0]=0;for (int i=1;i<= tot;++i) {int v=son[i];tmp=0;for (int j=0;j<=b[v];++j) Dep[j]=-oo; Get_dis (V,-1,black[v],fa[v]), int now=0,mx=-oo;for (int j=tmp;j>=0;--j) {if (k-flag-j<0) continue;while (now< =LEN&AMP;&AMP;NOW&LT;=K-FLAG-J) {Mx=max (Mx,mx_dep[now]); now++;} Ans=max (ANS,DEP[J]+MX);} if (Tmp>len) len=tmp;for (int j=len;j>=0;--j) {Mx_dep[j]=max (mx_dep[j],dep[j]);}} return;} void Get_div (int u) {DFS (u,-1); vis[u]=true;tot=0;for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]) Continue;son [++TOT]=V;FA[V]=G[I].W;} Sort (son+1,son+tot+1,cmp); Get_ans (U); for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (VIS[V]) continue;g=0;sum=w[v]; Get_g (v,-1); Get_div (g);} return;} int main () {int __size__=128<<20;char *__p__= (char*) malloc (__size__) +__size__;__asm__ ("Movl%0,%%esp\n":: "R" ( __p__)); Read (n); read (k); Read (m); for (int i=1;i<=m;++i) {read (u); black[u]=true;} for (int i=1;i<n;++i) {read (u); Read (v); Read (a); Add (u,v,a); add (v,u,a);} G=0;sum=n;f[0]=oo; Get_g (1,-1); Get_div (g);p rintf ("%d\n", ans); return 0;}

Codeforces Div1 C

A construction topic that asks you to assign a-Z letter to each point in the tree

Requires that if there are two nodes of the same letter, then the path between the two points must have a node of the letter is larger than the letters of the two nodes

Define A>b>c ...

In fact, the purpose of this problem impossible is to amuse you, there is no solution

My way of construction is to use the tree division, the structure of the tree divided into the LOGN layer, the first layer assigned a, the second level of B ...

It is not difficult to find the correctness of this assignment, since each layer is assigned a value that is smaller than the current number of subtrees trees, so the subtree is independent

Exactly satisfying the nature of tree Division and treatment

#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include < algorithm>using namespace Std;const int oo=0x7fffffff/3;const int maxn=100010;int n,u,v;int h[maxn],cnt=0;struct Edge{int To,next;} G[maxn<<1];int g,sum;int F[maxn],w[maxn];char ans[maxn];bool vis[maxn];void Add (int x,int y) {++cnt; G[cnt].to=y; g[cnt].next=h[x];h[x]=cnt;} void read (int &num) {Num=0;char Ch=getchar (); while (ch< '! ') Ch=getchar (); while (ch>= ' 0 ' &&ch<= ' 9 ') num=num*10+ch-' 0 ', Ch=getchar ();} void Cmax (int &a,int b) {if (b>a) a=b;} void get_g (int u,int fa) {f[u]=0;w[u]=1;for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]| | V==FA) continue; Get_g (V,u); W[u]+=w[v];cmax (F[u],w[v]);} Cmax (F[u],sum-w[u]); if (F[g]>f[u]) g=u;} void DFS (int u,int f) {w[u]=1;for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]| | V==F) Continue;dfs (v,u); w[u]+=w[v];} return;} void Get_div (int u,int d) {Vis[u]=true;dfs (u,-1); ans[u]=d+ ' A '; for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]) Continue;g=0;sum=w[v]; Get_g (v,-1); Get_div (g,d+1);} return;} int main () {read (n); for (int i=1;i<n;++i) {read (u); Read (v); add (u,v); add (v,u);} F[0]=oo;g=0;sum=n; Get_g (1,-1); Get_div (g,0), for (int i=1;i<=n;++i) {Putchar (ans[i]), if (i==n) printf ("\ n"), Else printf (""); return 0;}

Uva Live 7148

Given a tree, each point has a bit of power

Ask you to ask for a monotonous non-descending path on the tree, and the difference between the maximum and minimum values is not greater than D

The maximum length of the output path

Would have wanted to forcibly write O (Nlogn), struggled for a while and did not write it out

Have to write O (nlog^2n), the process of tree division to maintain a tree segment after the discussion can be

Every time full query a subtrees tree, insert a subtrees tree in full

The segment tree takes the weight value as the key value and retains the maximum length of the current weight.

#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include < algorithm>using namespace Std;const int maxn=100010;const int oo=0x7fffffff/3;int t,n,m,d,ans,mx;int u,v,kase,now; int c[maxn];int h[maxn],cnt=0;struct edge{int to,next;} G[maxn<<1];int g,sum,tim;bool vis[maxn];int f[maxn],w[maxn];int mx[maxn<<2];int t[maxn<<2];void Add (int x,int y) {++cnt; G[cnt].to=y; g[cnt].next=h[x];h[x]=cnt;} void read (int &num) {Num=0;char Ch=getchar (); while (ch< '! ') Ch=getchar (); while (ch>= ' 0 ' &&ch<= ' 9 ') num=num*10+ch-' 0 ', Ch=getchar ();} void Cmax (int &a,int b) {if (b>a) a=b;} void UPD (int o,int l,int r,int P,int v) {if (l==r) {if (t[o]!=tim) {t[o]=tim; Mx[o]=v;} else Cmax (mx[o],v); return;} int mid= (L+R) >>1;int l= (o<<1), r= (l|1), if (P<=mid) upd (l,l,mid,p,v), Else upd (r,mid+1,r,p,v); t[o]=tim; int a= (T[l]==tim? mx[l]:0); int b= (T[r]==tim? mx[r]:0); Mx[o]=max (A, b);} int ask (int o,int l,int r,int x,int y) {if (T[o]!=tim) return 0;if (l>=x&&r<=y) return Mx[o];int mid= (l+r) >>1;if (Y<=mid) return Ask (O<<1,l,mid,x,y), else if (x> MID) return ask (O<<1|1,mid+1,r,x,y), else return Max (ask (O<<1,l,mid,x,y), ask (O<<1|1,mid+1,r,x,y)) ;} void get_g (int u,int fa) {f[u]=0;w[u]=1;for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]| | V==FA) continue; Get_g (V,u); W[u]+=w[v];cmax (F[u],w[v]);} Cmax (F[u],sum-w[u]); if (F[g]>f[u]) g=u;} void DFS (int u,int f) {w[u]=1;for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]| | V==F) Continue;dfs (v,u); w[u]+=w[v];} return;} void get_up (int u,int f,int d) {int tmp=ask (1,1,mx,max (c[u]-d,1), C[u]), Cmax (ans,tmp+d+1); for (int i=h[u];i;i=g[i].next ) {int v=g[i].to;if (v==f| | VIS[V]) continue;if (c[v]>=c[u]&&c[v]-now<=d) get_up (v,u,d+1);} return;} void Get_down (int u,int f,int d) {int tmp=ask (1,1,mx,c[u],min)); Mx,c[u]+d (Cmax); for (int ans,tmp+d+1]. Next) {int v=g[i].to;if (v==f| | VIS[V]) continue;if (c[v]<=c[u]&&now-c[v]<=d) Get_down (v,u,d+1);} return;} void Dfs_down (int u,int f,int d) {UPD (1,1,mx,c[u],d); for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (v==f| | VIS[V]) continue;if (c[v]<=c[u]&&now-c[v]<=d) Dfs_down (v,u,d+1);} return;} void dfs_up (int u,int f,int d) {UPD (1,1,mx,c[u],d); for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (v==f| | VIS[V]) continue;if (c[v]>=c[u]&&c[v]-now<=d) dfs_up (v,u,d+1);} return;} void Get_div (int u) {Vis[u]=true;dfs (u,-1); tim++;for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]) continue;if ( C[v]>=c[u]&&c[v]-c[u]<=d) now=c[u],get_up (v,-1,1); if (C[v]<=c[u]&&c[u]-c[v]<=d) now=c [U],dfs_down (v,-1,1);} tim++;for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (vis[v]) continue;if (C[v]<=c[u]&&c[u]-c[v]<=d) Now=c[u],get_down (v,-1,1); if (C[v]>=c[u]&&c[v]-c[u]<=d) now=c[u],dfs_up (v,-1,1);} for (int i=h[u];i;i=g[i].next) {int v=g[i].to;if (VIS[V]) continue;g=0;sum=w[v]; Get_g (v,-1); Get_div (g);} return;} int main () {//freopen ("s.in", "R", stdin);//freopen ("S1.out", "w", stdout); reAD (T); while (t--) {read (n); read (D); mx=0;kase++;for (int i=1;i<=n;++i) read (C[i]), Mx=max (Mx,c[i]), memset (h,0, sizeof (h)); Cnt=0;memset (vis,false,sizeof (VIS)); for (int i=1;i<n;++i) {read (u); Read (v); add (u,v); add (v,u);} Ans=1;g=0;sum=n;f[0]=oo; Get_g (1,-1); Get_div (g);p rintf ("Case #%d:%d\n", Kase,ans);} return 0;}

The limpid A1486 tree

Given a tree, the tree has a bit of power, and each dot is either a black dot or a white point.

Find a path that passes at least k black dots, maximizing path XOR and

If there is no limit to k black dots, we can run on the trie directly.

Then we use the tree division to remove the K black point limit, the remaining problem is the bare trie qaq

The key is to have a black point limit when querying.

Seems to be able to use a durable trie?

My approach is to maintain an MX domain for trie nodes, which represents the maximum number of black dots for the leaf nodes that the subtree expands.

So that we can be greedy on the trie to judge on the Qaq

#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include < algorithm>using namespace Std;const int oo=0x7fffffff/3;const int maxn=100010;int n,k,u,v,ans;int black[maxn],c[ Maxn];bool vis[maxn];int h[maxn],cnt=0;struct edge{int to,next;} G[maxn<<1];int g,tot,sum;int mx[5000010];int nxt[5000010][2];int f[maxn],w[maxn];void Add (int x,int y) {++cnt; G[cnt].to=y; g[cnt].next=h[x];h[x]=cnt;}    void read (int &num) {Num=0;char Ch=getchar (); while (ch< '! ')    Ch=getchar (); while (ch>= ' 0 ' &&ch<= ' 9 ') num=num*10+ch-' 0 ', Ch=getchar ();} void Cmax (int &a,int b) {if (b>a) a=b;}    void get_g (int u,int fa) {f[u]=0;w[u]=1;        for (int i=h[u];i;i=g[i].next) {int v=g[i].to; if (vis[v]| |        V==FA) continue;        Get_g (V,u); w[u]+=w[v];    Cmax (F[u],w[v]);    }cmax (F[u],sum-w[u]); if (F[g]>f[u]) g=u;}    void DFS (int u,int f) {w[u]=1;        for (int i=h[u];i;i=g[i].next) {int v=g[i].to; if (vis[v]| | V==F) contInue;    DFS (V,u); w[u]+=w[v]; }return;}    int Newnode () {tot++;nxt[tot][0]=nxt[tot][1]=0; Mx[tot]=0;return tot;}    void Insert (int num,int k) {int now=1;        for (int i=31;i>=0;--i) {int id= (num>>i&1);        if (!nxt[now][id]) nxt[now][id]=newnode ();    Now=nxt[now][id];mx[now]=max (MX[NOW],K); }return;}    int ask (int num,int k) {int now=1,l=nxt[now][1],r=nxt[now][0];    if (mx[l]<k&&mx[r]<k) return-1;    int ans=0;        for (int i=31;i>=0;--i) {int id= (num>>i&1); id^=1;            if (nxt[now][id]&&mx[nxt[now][id]]>=k) {ans|= (1<<i);        Now=nxt[now][id];    }else Now=nxt[now][id^1]; }return ans;}    void Get_ans (int u,int f,int d,int b) {int tmp=ask (d,k-b); Ans=max (ans,tmp);        for (int i=h[u];i;i=g[i].next) {int v=g[i].to; if (vis[v]| |        V==F) continue;    Get_ans (V,u,d^c[v],b+black[v]); }return;}    void Get_insert (int u,int f,int d,int b) {insert (D,B); for (int i=h[u];i;I=g[i].next) {int v=g[i].to; if (vis[v]| |        V==F) continue;    Get_insert (V,u,d^c[v],b+black[v]); }return;}    void Get_div (int u) {tot=1;nxt[tot][0]=nxt[tot][1]=0;    Insert (0,0);    if (black[u]>=k) Ans=max (Ans,c[u]);    Vis[u]=true;dfs (u,-1);        for (int i=h[u];i;i=g[i].next) {int v=g[i].to;        if (Vis[v]) continue;        Get_ans (V,-1,c[u]^c[v],black[v]+black[u]);    Get_insert (V,-1,c[v],black[v]);        } for (int i=h[u];i;i=g[i].next) {int v=g[i].to;        if (Vis[v]) continue;        G=0;SUM=W[V]; Get_g (v,-1);    Get_div (g); }return;}    int main () {read (n); read (k);    for (int i=1;i<=n;++i) read (Black[i]);    for (int i=1;i<=n;++i) read (C[i]);        for (int i=1;i<n;++i) {read (u); Read (v);    Add (u,v); add (V,u);    }ans=-1;    G=0;sum=n;f[0]=oo; Get_g (1,-1);    Get_div (g);    printf ("%d\n", ans); return 0;}

Tree division usually solves the problem of the tree path

A wide range of applications can be used to optimize the problem can also be used to count

There is also a part of the problem of partition of the tree using the nature of the center of gravity and the structure of the LOGN layer of tree Division

If you encounter tree path-related problems, you might want to try it out with a tree.

Tree Division seems to be compatible with a lot of data structures to maintain information?

Several topics to be completed:

Two trees divide and cure +fft

And the love of a bauhinia flower.

Some knowledge points of the pit:

Palindrome Related Exercises

Can be persisted trie

Summary on the review of tree division and treatment

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.