luogu P8274 [USACO22OPEN] Balancing a Tree G
题面传送门
感觉一道比较精妙的题目。但是我的做法好像很暴力
首先考虑确定根节点权值以后怎么做。
对于每个节点,考虑其到根的路径上的节点,可以发现只有最大值和最小值是有用的。
这个点的取值只有三种情况:左端点,右端点,最大值和最小值的中值(如果在这个区间里的话)。
等等,我们好像没有考虑对下面点的影响?
实际上只要这个点最优,对下面的影响就最小。因为最后一种对最大值和最小值是没有影响,可以忽略。前两种取到最优的时候恰好是对最大最小值影响最低的时候。
然后剩下根节点的取值,发现看上去一脸三分,然后就过了。
时间复杂度\(O(n\log W)\)
code:
#include
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (100000+5)
#define M (900+5)
#define K (200000+5)
#define mod 9248440332
#define Mod (mod-1)
#define eps (1e-9)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;vector S[N];
int n,m,k,x,y,z,T,B,H,L[N],R[N],P[N],l,r,m1,m2,Ans,Pus;
struct Ques{int x,w;}Q[4];I bool cmp(Ques x,Ques y){return x.w=L[x]&&(Mx+Mi)/2<=R[x]&&(Q[++H]=(Ques){(Mx+Mi)/2,(Mx-Mi+1)/2},0);
sort(Q+1,Q+H+1,cmp);P[x]=Q[1].x;Pus=max(Pus,Q[1].w);for(int i:S[x]) dfs(i,max(Mx,P[x]),min(Mi,P[x]));
}
I int CK(int mid){Pus=0;P[1]=mid;for(int i:S[1]) dfs(i,P[1],P[1]);return Pus;}
I void Solve(){
int i;for(i=1;i<=n;i++) S[i].clear();scanf("%d",&n);for(i=2;i<=n;i++) scanf("%d",&x),S[x].PB(i);for(i=1;i<=n;i++) scanf("%d%d",&L[i],&R[i]);
l=L[1];r=R[1];while(l+2