bzoj1758 [Wc2010]重建計劃
Description
Input
第一行包含一個正整數N,表示X國的城市個數. 第二行包含兩個正整數L和U,表示政策要求的第一期重建方案中修建道路數的上下限 接下來的N-1行描述重建小組的原有方案,每行三個正整數Ai,Bi,Vi分別表示道路(Ai,Bi),其價值為Vi 其中城市由1..N進行標號
Output
輸出最大平均估值,保留三位小數
Sample Input
42 3
1 2 1
1 3 2
1 4 3
Sample Output
2.500HINT
N<=100000,1<=L<=U<=N-1,Vi<=1000000 新加數據一組 By leoly,但未重測..2016.9.27
正解:分數規劃+點分治+單調隊列?。
好吧這題我是壓常數過去的,並沒有用單調隊列。。
顯然,外層二分答案,然後每條邊都減去$mid$,判斷是否能找到長度屬於$[l,r]$且路徑和$>0$的路徑。
那麽我們點分治,在每一層依次遞歸重心的所有子樹,合並答案就行了,但是屬於$[l,r]$這個條件不好處理。正解似乎是單調隊列,然而我用的是線段樹,復雜度多一個$log$。。
不過還是跑過去了,具體是怎麽壓常數的呢?
1.加$register$,可以快$2s$。
2.手寫$min$,$max$函數,使用三目運算符,可以快將近$1s$。
3.如果當前答案已經$>0$,直接退出分治,但是這個好像對於特意構造的數據作用不大。
4.把每棵子樹中深度相同的結點權值直接取$max$,並且記下這些深度,這樣可以節省線段樹的插入。
5.預處理出所有的重心和在每一層的最大深度,可以快$1s$。
6.用$zkw$線段樹,且因為線段樹是以深度為區間的,所以我們每一層分治時的線段樹就以當前最大深度為上界,這樣線段樹消耗的$log$可以大大減少。應該說,這個壓常是最優秀的,它讓線段樹的$log$幾乎變成了常數,我大概計算了一下,每層改變線段樹上界好像使得$log^{2}n$變成了$3log$左右的常數?
大概用這些壓常技巧,就能通過這題了。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3#include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1e18) 15 #define eps (3e-4) 16 #define N (100010) 17 #define ls (x<<1) 18 #define rs (x<<1|1) 19 #define il inline 20 #define RG register 21 #define ll long long 22 #define min(a,b) (a<b ? a : b) 23 #define max(a,b) (a>b ? a : b) 24 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 25 26 using namespace std; 27 28 struct edge{ int nt,to,dis; }g[N<<1]; 29 30 int head[N],st[N],vi[N],vi1[N],vis[N],dep[N],son[N],sz[N],ss[N],RT[N][19],Dp[N][19],n,l,r,num,top,bit,Mx_dep; 31 double sum[N<<2],dis[N],mx[N],L,R,mid,res,ans; 32 33 il int gi(){ 34 RG int x=0,q=1; RG char ch=getchar(); 35 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 36 if (ch==‘-‘) q=-1,ch=getchar(); 37 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 38 return q*x; 39 } 40 41 il void insert(RG int from,RG int to,RG int dis){ 42 g[++num]=(edge){head[from],to,dis},head[from]=num; return; 43 } 44 45 il void build(){ for (RG int i=1;i<=bit+n;++i) sum[i]=-inf; return; } 46 47 il void update0(RG int x,RG double y){ 48 for (x+=bit,sum[x]=max(sum[x],y),x>>=1;x;x>>=1) sum[x]=max(sum[ls],sum[rs]); return; 49 } 50 51 il void update1(RG int x){ 52 for (sum[x+=bit]=-inf,x>>=1;x;x>>=1) sum[x]=-inf; return; 53 } 54 55 il double query(RG int l,RG int r){ 56 RG double res=-inf; 57 for (l+=bit-1,r+=bit+1;l^r^1;l>>=1,r>>=1){ 58 if (~l&1) res=max(res,sum[l^1]); 59 if (r&1) res=max(res,sum[r^1]); 60 } 61 return res; 62 } 63 64 il void getroot(RG int x,RG int p,RG int S,RG int &rt){ 65 sz[x]=1,son[x]=0; RG int v; 66 for (RG int i=head[x];i;i=g[i].nt){ 67 v=g[i].to; if (v==p || vis[v]) continue; 68 getroot(v,x,S,rt),sz[x]+=sz[v]; 69 son[x]=max(son[x],sz[v]); 70 } 71 son[x]=max(son[x],S-sz[x]); 72 if (son[rt]>=son[x]) rt=x; return; 73 } 74 75 il void getdep(RG int x,RG int p){ 76 dep[x]=dep[p]+1,Mx_dep=max(Mx_dep,dep[x]); RG int v; 77 for (RG int i=head[x];i;i=g[i].nt){ 78 v=g[i].to; if (v==p || vis[v]) continue; 79 getdep(v,x); 80 } 81 return; 82 } 83 84 il void getdis(RG int x,RG int p,RG double key){ 85 dep[x]=dep[p]+1,sz[x]=1; RG int v,k=dep[x]; 86 if (!vi[k]) st[++top]=k,vi[k]=1; mx[k]=max(mx[k],dis[x]); 87 for (RG int i=head[x];i;i=g[i].nt){ 88 v=g[i].to; if (v==p || vis[v]) continue; 89 dis[v]=dis[x]+g[i].dis-key; 90 getdis(v,x,key),sz[x]+=sz[v]; 91 } 92 return; 93 } 94 95 il void solve0(RG int x,RG int S,RG int level){ 96 RG int rt=0,v; Mx_dep=0,son[0]=S; 97 getroot(x,0,S,rt),vis[rt]=1,RT[x][level]=rt; 98 for (RG int i=head[rt];i;i=g[i].nt){ 99 v=g[i].to; if (!vis[v]) getdep(v,0); 100 } 101 Dp[x][level]=Mx_dep; 102 for (RG int i=head[rt];i;i=g[i].nt){ 103 v=g[i].to; if (!vis[v]) solve0(v,sz[v],level+1); 104 } 105 return; 106 } 107 108 il int solve(RG int x,RG int S,RG int level,RG double key){ 109 RG int rt=RT[x][level],Mx=Dp[x][level],tp=0,v; vis[rt]=1; 110 for (bit=1;bit<=Mx+1;bit<<=1); 111 for (RG int i=head[rt];i;i=g[i].nt){ 112 v=g[i].to; if (vis[v]) continue; 113 top=0,dis[v]=g[i].dis-key,getdis(v,0,key); 114 for (RG int j=1,L,R,k;j<=top;++j){ 115 k=st[j]; if (l<=k && k<=r) res=max(res,mx[k]); if (res>eps) return 1; 116 if (!vi1[k]) ss[++tp]=k,vi1[k]=1; L=max(l-k,1),R=min(r-k,Mx); 117 if (L<=R) res=max(res,mx[k]+query(L,R)); if (res>eps) return 1; 118 } 119 for (RG int j=1,k;j<=top;++j) 120 k=st[j],update0(k,mx[k]),mx[k]=-inf,vi[k]=0; 121 } 122 for (RG int i=1;i<=tp;++i) update1(ss[i]),vi1[ss[i]]=0; 123 for (RG int i=head[rt];i;i=g[i].nt){ 124 v=g[i].to; if (!vis[v]) if (solve(v,sz[v],level+1,key)) return 1; 125 } 126 return res>eps; 127 } 128 129 il void work(){ 130 n=gi(),l=gi(),r=gi(),L=inf; 131 for (RG int i=1,u,v,w;i<n;++i) 132 u=gi(),v=gi(),w=gi(),insert(u,v,w),insert(v,u,w),L=min(L,w),R=max(R,w); 133 solve0(1,n,0); 134 while (R-L>eps){ 135 mid=(L+R)*0.5,res=-inf; for (bit=1;bit<=n+1;bit<<=1); build(); 136 for (RG int i=1;i<=n;++i) mx[i]=-inf,vi[i]=vi1[i]=vis[i]=0; 137 if (solve(1,n,0,mid)) ans=mid,L=mid; else R=mid; 138 } 139 printf("%0.3lf\n",ans); return; 140 } 141 142 int main(){ 143 File("rebuild"); 144 work(); 145 return 0; 146 }
bzoj1758 [Wc2010]重建計劃