对于边来说,一棵树上除了根节点,每一个结点都唯一对应了一条边,那么就很好将边转换为点的问题了
树链剖分+线段树
注意根节点查询时候的取舍问题
#include #include #include #include #include #include #include #include #include #include //#pragma comment(linker, "/STACK:1024000000,1024000000"); using namespace std; #define INF 0x3f3f3f3f #define maxn 20003 int n; int x[maxn],y[maxn]; int fir[maxn],u[maxn],v[maxn],w[maxn],nex[maxn]; int e_max; int mx[maxn],mxt[maxn],mix[4*maxn]; int tot; int son[maxn],siz[maxn],pos[maxn],fa[maxn],top[maxn],deep[maxn]; void init_() { tot=0; memset(fir,-1,sizeof fir); memset(son,-1,sizeof son); memset(siz,0,sizeof siz); e_max=0; } inline void add_edge(int s,int t,int c) { int e=e_max++; u[e]=s; v[e]=t; w[e]=c; nex[e]=fir[s]; fir[s]=e; } void dfs1(int k,int pre,int d) { deep[k]=d; fa[k]=pre; siz[k]++; for(int i=fir[k]; ~i; i=nex[i]) { int e=v[i]; if(e!=pre) { mxt[e]=w[i]; dfs1(e,k,d+1); siz[k]+=siz[e]; if(son[k]==-1||siz[son[k]]>1; init(l,mid,k<<1); init(mid+1,r,k<<1|1); mix[k]=max(mix[k<<1],mix[k<<1|1]); } inline void update(int d,int s,int l,int r,int k) { if(s==l&&r==s) { mix[k]=d; return ; } int mid=l+r>>1; if(s<=mid) update(d,s,l,mid,k<<1); else update(d,s,mid+1,r,k<<1|1); mix[k]=max(mix[k<<1],mix[k<<1|1]); } inline int query(int s,int t,int l,int r,int k) { if(s==l&&r==t) { return mix[k]; } int mid=l+r>>1; if(t<=mid) return query(s,t,l,mid,k<<1); else if(s>mid) return query(s,t,mid+1,r,k<<1|1); else return max(query(s,mid,l,mid,k<<1),query(mid+1,t,mid+1,r,k<<1|1)); } void Query(int s,int t) { int ans=0; int f1=top[s],f2=top[t]; while(f1!=f2) { if(deep[f1]deep[t]) swap(s,t); ans=max(ans,query(pos[s]+1,pos[t],1,tot-1,1)); printf("%d\n",ans); } int main() { int T; scanf("%d",&T); while(T--) { init_(); scanf("%d",&n); for(int i=1; i