点分治求卡常 or 优化

P4292 [WC2010] 重建计划

现在改了优化 90 了: ```cpp #include<bits/stdc++.h> using namespace std; const int N=1e5+5; const double INF=1e9,eps=1e-6; int n,L,U,sz[N],mx[N],len[N],deq[N],q[N],vis[N],viss[N],top,last,flag,rt,sum,cnt,G[N]; vector<pair<int,double> >v[N]; double dis[N],f[N]; void getrt(int u,int faa) { sz[u]=1;mx[u]=0; for(auto t:v[u]) { if(t.first==faa||vis[t.first])continue; getrt(t.first,u); sz[u]+=sz[t.first]; mx[u]=max(mx[u],sz[t.first]); } mx[u]=max(mx[u],sum-sz[u]); if(mx[u]<mx[rt])rt=u; return; } void bfs(int src) { viss[q[++top]=src]=1; for(int i=last+1;i<=top;i++) { int u=q[i]; for(auto t:v[u]) { if(vis[t.first]||viss[t.first])continue; dis[t.first]=dis[u]+t.second; len[t.first]=len[u]+1; viss[q[++top]=t.first]=1; } } for(int i=last+1;i<=top;i++)viss[q[i]]=0; return; } void check() { int h=1,t=0,tip=last+1; for(int i=min(U,len[q[top]]);i;i--) { int tl=i>=L?0:L-i,tr=U-i; while(h<=t&&len[deq[h]]<tl)++h; while(tip<=top&&len[q[tip]]<tl)++tip; while(tip<=top&&len[q[tip]]<=tr) { while(h<=t&&dis[deq[t]]+eps<=dis[q[tip]])--t; deq[++t]=q[tip++]; } if(h<=t&&f[i]+dis[deq[h]]>=-eps) { flag=1; return; } } } void calc(int u) { f[0]=dis[u]=len[u]=0;top=0; q[0]=u; for(auto t:v[u]) { if(vis[t.first])continue; dis[t.first]=t.second; len[t.first]=1; last=top; bfs(t.first); check(); for(int i=last+1;i<=top;i++) f[len[q[i]]]=max(f[len[q[i]]],dis[q[i]]); } for(int i=0;i<=top;i++)f[len[q[i]]]=-INF; return; } void solve() { int u=G[++cnt]; vis[u]=1;calc(u); for(auto t:v[u]) { if(!vis[t.first]) solve(); } vis[u]=0; return; } bool check(double mid) { // memset(vis,0,sizeof vis); for(int i=1;i<=n;i++) for(auto &t:v[i])t.second-=mid; flag=0;cnt=0; solve(); for(int i=1;i<=n;i++) for(auto &t:v[i])t.second+=mid; return flag; } void init(int u) { mx[rt=0]=INF; getrt(u,0); G[++cnt]=rt; vis[rt]=1; int x=rt; for(auto t:v[rt]) { if(!vis[t.first])sum=sz[t.first],init(t.first); } vis[x]=0; return; } int main() { clock_t c1=clock(); #ifdef LOCAL freopen("1.in","r",stdin); freopen("1.out","w",stdout); #endif ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); cin>>n>>L>>U; double l=0,r=0; for(int i=1;i<=n-1;i++) { int a,b,c; cin>>a>>b>>c; r+=c; v[a].push_back(make_pair(b,c)); v[b].push_back(make_pair(a,c)); f[i]=-INF; } // sz[1]=n; sum=n; init(1); while(l<=r-eps) { double mid=(l+r)/2.0; if(check(mid))l=mid; else r=mid-eps; } printf("%.3lf",l); #ifdef LOCAL cerr<<"Time used:"<<clock()-c1<<"ms"; #endif return 0; } ```
by AAA404 @ 2024-02-04 20:17:09


@[AAA404](/user/723198) 你考虑加几个剪枝,我几个月前写这题时也被卡了,加个剪枝就过了。具体的我不记得了。
by Saka_Noa @ 2024-02-04 20:20:32


```cpp void dfs(int u, int Fa, long double len) { de[u] = de[Fa] + 1; if (g[de[u] - 1] <= len) // this { g[de[u] - 1] = len; id_g[de[u] - 1] = u; } for (int i = head[u]; i; i = e[i].next) { int v = e[i].to; if (v == Fa || vis[v]) continue; dfs(v, u, len + (e[i].w - Check_X)); } } ``` 我好像是加了这个
by Saka_Noa @ 2024-02-04 20:24:07


好像不是,我再看看。
by Saka_Noa @ 2024-02-04 20:25:01


@[Saka_Noa](/user/498612) 精度改成 1e-4 就过了....难蚌
by AAA404 @ 2024-02-04 20:25:11


此帖终
by AAA404 @ 2024-02-04 20:25:25


@[AAA404](/user/723198) ```cpp void solve(int u) { vis[u] = 1; calc(u); if (ans >= 0) return; for (int i = head[u]; i; i = e[i].next) { int v = e[i].to; if (vis[v]) continue; root = de[u] = de[v] = 0; sum = si[v]; if (si[v] < in_l) //this continue; get_core(v, 0); pre_dfs(root, 0); //if (dep[root] < in_l) // return; solve(root); } } ``` 想起来了
by Saka_Noa @ 2024-02-04 20:28:38


@[Saka_Noa](/user/498612) `in_l` 是什么
by AAA404 @ 2024-02-04 20:30:47


@[AAA404](/user/723198) 题目输入边界 `l`
by Saka_Noa @ 2024-02-04 20:32:26


@[AAA404](/user/723198) 可以优化我写的点分治 $0.5s$ 左右。
by Saka_Noa @ 2024-02-04 20:37:35


| 下一页