By sumix173
思路很棒!
每個點記錄兩個信息:f[i][j]表示i的子樹中深度為j的節點的個數。g[i][j]表示滿足d[a]-2*d[lca(a,b)]=d[b]-2*d[lca(a,b)]的二元點對(a,b)的個數。
從下向上啟發式合並,每次將輕兒子的信息合並到重兒子上,總的時間復雜度為O(nlogn)。在合並的過程中同時計算出答案。
#include<iostream> #include<cstdio> #include<cstring> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define pa pair<int,int> #define maxn 50005 #define inf 1000000000 using namespace std; int n,m,block,l,r,mx; int a[maxn],pos[maxn],pl[maxn],pr[maxn],ans[maxn]; bool vst[maxn]; stack<pa> st; struct data{int l,r,id;}b[maxn]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline bool cmp(data x,data y) { return pos[x.l]==pos[y.l]?x.r<y.r:x.l<y.l; .l="read();b[i].r=read();b[i].id=i;" block="int(sqrt(n));" bool="" data="" if="" inline="" int="" l="pos[b[i].l]*block;" mx="max(mx,tr-tl+1);" n="read();m=read();" pre="" r="l-1;" return="" tl="x,tr=x;" tmp="mx;" tr="pr[x+1];" void="" while=""><p> </p> </y.r:x.l<y.l;></pa></int,int></stack></algorithm></cmath></cstring></cstring></cstdio></iostream>