51 nod 1297 管理二叉树
原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1297
先是暴力加优化T了最后两个点……
我还是来想想正解吧。
先写棵线段树把二叉搜索树建出来,然后在树上做下点分治就好了。
#include<cstdio> #include<cstring> #include<algorithm> #define lp (p<<1) #define rp ((p<<1)|1) using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } struct na{int y,z,ne,k;}b[200001],B[4000001]; int n,m,a[200001],x,y,l[200001],num=0,de[200001],L[200001],Num=0,s[200001],Si,ro,ma; bool bo[200001]; long long mmh[200001][5],S[200001][5]; long long MMH=0; inline void in(int x,int y){b[++num].y=y;b[num].ne=l[x];l[x]=num;} inline void In(int x,int y,int z,int k){B[++Num].y=y;B[Num].z=z;B[Num].k=k;B[Num].ne=L[x];L[x]=Num;} struct tree{int ma,mi;}t[4000001]; void add(int p,int l,int r,int v){ if (a[t[p].ma]<a[v]||t[p].ma==0) t[p].ma=v; if (a[t[p].mi]>a[v]||t[p].mi==0) t[p].mi=v; if (l==r) return; int mid=l+r>>1; if (a[v]<=mid) add(lp,l,mid,v);else add(rp,mid+1,r,v); } int quea(int p,int l,int r,int R){ if (R>=r) return t[p].ma; int mid=l+r>>1; if (R<=mid) return quea(lp,l,mid,R);else if (mid=quea(rp,mid+1,r,R)) return mid;else return t[lp].ma; } int quei(int p,int l,int r,int R){ if (R<=l) return t[p].mi; int mid=l+r>>1; if (R>mid) return quei(rp,mid+1,r,R);else if (mid=quei(lp,l,mid,R)) return mid;else return t[rp].mi; } void gs(int x,int f){ s[x]=1; int u=0; for (register int i=l[x];i;i=b[i].ne) if (b[i].y!=f&&!bo[b[i].y]){ gs(b[i].y,x); s[x]+=s[b[i].y]; if (u<s[b[i].y]) u=s[b[i].y]; } if (Si-s[x]>u) u=Si-s[x]; if (u<ma) ma=u,ro=x; } void dfs(int x,int f,int r,int z,int k){ s[x]=1; In(x,r,z,k); for (register int i=l[x];i;i=b[i].ne) if (!bo[b[i].y]&&b[i].y!=f) dfs(b[i].y,x,r,z+1,k),s[x]+=s[b[i].y]; } void work(int x,int S){ Si=S;ma=1e9;gs(x,0);bo[x=ro]=1; int u=0; for (register int i=l[x];i;i=b[i].ne) if (!bo[b[i].y]) dfs(b[i].y,x,x,1,++u);In(x,x,0,++u); for (register int i=l[x];i;i=b[i].ne) if (!bo[b[i].y]) work(b[i].y,s[b[i].y]); } int main(){ register int i,j; n=read();a[n+1]=n+1;add(1,0,n+1,0);add(1,0,n+1,n+1); a[1]=read();add(1,0,n+1,1);de[1]=1; for (i=2;i<=n;i++){ a[i]=read(); x=quea(1,0,n+1,a[i]-1);y=quei(1,0,n+1,a[i]+1); if (de[x]>de[y]){ in(x,i); in(i,x); de[i]=de[x]+1; }else{ in(y,i); in(i,y); de[i]=de[y]+1; } add(1,0,n+1,i); } work(1,n); for (i=1;i<=n;i++){ for (j=L[i];j;j=B[j].ne) MMH+=1LL*B[j].z*(S[B[j].y][0]-S[B[j].y][B[j].k])+mmh[B[j].y][0]-mmh[B[j].y][B[j].k], mmh[B[j].y][0]+=B[j].z,mmh[B[j].y][B[j].k]+=B[j].z,S[B[j].y][0]++,S[B[j].y][B[j].k]++; printf("%lld\n",MMH); } }