luogu P8274 [USACO22OPEN] Balancing a Tree G
阿新 • • 發佈:2022-04-04
題面傳送門
感覺一道比較精妙的題目。但是我的做法好像很暴力
首先考慮確定根節點權值以後怎麼做。
對於每個節點,考慮其到根的路徑上的節點,可以發現只有最大值和最小值是有用的。
這個點的取值只有三種情況:左端點,右端點,最大值和最小值的中值(如果在這個區間裡的話)。
等等,我們好像沒有考慮對下面點的影響?
實際上只要這個點最優,對下面的影響就最小。因為最後一種對最大值和最小值是沒有影響,可以忽略。前兩種取到最優的時候恰好是對最大最小值影響最低的時候。
然後剩下根節點的取值,發現看上去一臉三分,然後就過了。
時間複雜度\(O(n\log W)\)
code:
#include<bits/stdc++.h> #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<int> 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<y.w;} I void dfs(int x,int Mx,int Mi){ H=0;Q[++H]=(Ques){L[x],max(abs(L[x]-Mx),abs(L[x]-Mi))};Q[++H]=(Ques){R[x],max(abs(R[x]-Mx),abs(R[x]-Mi))};(Mx+Mi)/2>=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<r) m1=l+(r-l)/3,m2=r-(r-l)/3,CK(m1)<CK(m2)?(r=m2):(l=m1);Ans=1e9;for(i=l;i<=r;i++) x=CK(i),Ans=min(Ans,x); //cerr<<' '<<CK(1)<<'\n'; printf("%d\n",Ans);if(!B) return;for(i=l;i<=r;i++) if(CK(i)==Ans) {printf("%d ",i);break;}for(i=2;i<=n;i++) printf("%d ",P[i]);Pc('\n'); } int main(){ freopen("1.in","r",stdin); scanf("%d%d",&T,&B);while(T--) Solve(); }