BZOJ 1758

mengbing。。。。。

大家都说这是一道卡常题 、名不虚传、233333

树分治 再加上迭代答案 而不是二分 就可以过了

迭代的次数 平均下来 大概就只有 2.8次的样子

需要单调队列优化更新答案的过程

  1 #include <bits/stdc++.h>
  2 #define N 100010
  3 #define inf 1e10
  4 using namespace std;
  5 inline int read()
  6 {
  7     int x=0,f=1; char ch=getchar();
  8     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1; ch=getchar();}
  9     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();}
 10     return x*f;
 11 }
 12 struct edge
 13 {
 14     int v,next,w;
 15 }vs[N<<1];
 16 int n,L,R,q[N],vis[N],sum,Rtt;
 17 int st[N],ee,Rt,size[N],tp[N],dep[N];
 18 int stk[N],top,fa[N],mxd;
 19 double prestans=0.0,ans,vopt[N],,f[N];
 20 vector <int> Gp[N];
 21 inline void addedge(int u,int v,int w)
 22 {
 23     vs[++ee].v=v;vs[ee].w=w;
 24     vs[ee].next=st[u];st[u]=ee;
 25 }
 26 void dfs1(int rt,int pr)
 27 {
 28     size[rt]=1;
 29     for(int i=st[rt];i;i=vs[i].next)
 30     {
 31         if(vs[i].v==pr||vis[vs[i].v]) continue;
 32         dfs1(vs[i].v,rt);
 33         size[rt]+=size[vs[i].v];
 34     }
 35 }
 36 void dfs2(int rt,int pr)
 37 {
 38     tp[rt]=0;
 39     for(int i=st[rt];i;i=vs[i].next)
 40     {
 41         if(vs[i].v==pr||vis[vs[i].v]) continue;
 42         dfs2(vs[i].v,rt);
 43         tp[rt]=max(tp[rt],size[vs[i].v]);
 44     }
 45     tp[rt]=max(tp[rt],sum-size[rt]);
 46     if(tp[rt]<tp[Rtt]) Rtt=rt;
 47 }
 48 void predeal(int rt)
 49 {
 50     vis[rt]=1;
 51     for(int i=st[rt];i;i=vs[i].next)
 52     {
 53         if(vis[vs[i].v]) continue;
 54         Rtt=0; dfs1(vs[i].v,rt);
 55         sum=size[vs[i].v];
 56         dfs2(vs[i].v,rt);
 57         Gp[rt].push_back(Rtt);
 58         predeal(Rtt);
 59     }
 60 }
 61 void getans(int rt,int val)
 62 {
 63     stk[top=1]=rt; fa[1]=0; f[1]=val; dep[1]=1;
 64     for(int i=1;i<=top;i++)
 65     {
 66         for(int j=st[stk[i]];j;j=vs[j].next)
 67         {
 68             if(vis[vs[j].v]||vs[j].v==fa[i]) continue;
 69             stk[++top]=vs[j].v; dep[top]=dep[i]+1;
 70             fa[top]=stk[i]; f[top]=f[i]+vs[j].w;
 71         }
 72     }
 73     int l=1,r=0,pre=mxd;
 74     for(int i=1,j;i<=top;i=j)
 75     {
 76         double mx=-inf;
 77         for(j=i;dep[j]==dep[i]&&j<=top;j++)
 78             mx=max(mx,f[j]);
 79         while(pre>=0&&pre>=L-dep[i])
 80         {
 81             while(vopt[q[r]]<vopt[pre]&&r>=l) r--;
 82             q[++r]=pre; pre--;
 83         }
 84
 85         while(q[l]+dep[i]>R&&l<=r) l++;
 86         if(l<=r) ans=max(ans,(vopt[q[l]]+mx+prestans*q[l])/(q[l]+dep[i]));
 87     }
 88     for(int i=1;i<=top;i++)
 89         vopt[dep[i]]=max(vopt[dep[i]],f[i]-dep[i]*prestans);
 90     mxd=max(mxd,dep[top]);
 91 }
 92 void solve(int rt)
 93 {
 94     vis[rt]=1; mxd=0; vopt[0]=0;
 95     for(int i=st[rt];i;i=vs[i].next)
 96     {
 97         if(vis[vs[i].v]) continue;
 98         getans(vs[i].v,vs[i].w);
 99     }
100     for(int i=0;i<=mxd;i++) vopt[i]=-inf;
101     for(unsigned i=0;i<Gp[rt].size();i++)
102         solve(Gp[rt][i]);
103 }
104 double check()
105 {
106     memset(vis,0,sizeof vis);
107     ans=-inf;
108     solve(Rt);
109     return ans;
110 }
111 int main()
112 {
113     //freopen("read.in","r",stdin);
114     n=read();L=read();R=read();
115     for(int i=1;i<n;i++)
116     {
117         int x=read(),y=read(),w=read();
118         addedge(x,y,w);addedge(y,x,w);
119     }
120     dfs1(1,0);
121     Rtt=0; tp[0]=n+1; sum=n;
122     dfs2(1,0);
123     Rt=Rtt; predeal(Rt);
124     for(int i=1;i<=n;i++) vopt[i]=-inf;
125         for(int i=1;i<=3;i++)
126         prestans=check();
127     printf("%.3lf",prestans);
128     return 0;
129 }

↓↓↓↓ dmk ↓↓↓↓

 1 #include <bits/stdc++.h>
 2 #define N 100000
 3 using namespace std;
 4
 5 struct edge
 6 {
 7     int u,v,next,w;
 8 }vs[N<<1];
 9 int st[N+100],ee,dep[N+100],mx1,mx2;
10 inline void addedge(int u,int v,int w)
11 {
12     vs[++ee].v=v;vs[ee].next=st[u];
13     vs[ee].u=u;vs[ee].w=w;st[u]=ee;
14 }
15 int main()
16 {
17     srand(time(0));
18     freopen("read.in","w",stdout);
19     printf("%d\n",N);
20     for(int i=2;i<=N;i++)
21     {
22         int u=rand()*rand()%(i-1)+1;
23         addedge(u,i,rand()*rand()%1000000);
24         dep[i]=dep[u]+1;
25         if(dep[i]>=mx1) mx2=mx1,mx1=dep[i];
26         else if(dep[i]>mx2) mx2=dep[i];
27     }
28     int L=rand()*rand()%(mx1+mx2)+1,R=rand()*rand()%(mx1+mx2)+1;
29     if(L>R) swap(L,R);
30 /*     sort(dep+1,dep+1+N);
31     for(int i=1;i<=N;i++)
32         printf("%d ",dep[i]); printf("\n"); */
33     printf("%d %d\n",L,R);
34     for(int i=1;i<=N;i++)
35         printf("%d %d %d\n",vs[i].u,vs[i].v,vs[i].w);
36     return 0;
37 }

好好讲道理 应该求出直径 所以这个dmk 有问题2333 但总体还是能拍得出来 逃

时间: 2024-12-11 09:57:56

BZOJ 1758的相关文章

【BZOJ 1758】 [Wc2010]重建计划

1758: [Wc2010]重建计划 Time Limit: 40 Sec  Memory Limit: 162 MB Submit: 989  Solved: 345 [Submit][Status] Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai,Bi,Vi分别表示道路(Ai,Bi),其价值为Vi 其中城市由1..N进行标

[BZOJ]1758: [Wc2010]重建计划

题目大意:给定一棵n个点的带边权的树和l,u,求长度在[l,u]之间平均权值最大的链的权值.(n<=100,000) 思路:二分答案,把树上每条边减去二分出的答案,点分治check是否有长度在[l,u]之间权值和大等0的链,每次把每棵子树按深度排序,记下各个深度到根距离最大的节点,再用单调队列统计即可,总复杂度O(nlogn^2).此题卡常差评,重心只要算一次,不用每次二分都算,稍微卡卡就过了. #include<cstdio> #include<cstring> #incl

【BZOJ 1758】【WC 2010】重建计划 分数规划+点分治+单调队列

一开始看到$\frac{\sum_{}}{\sum_{}}$就想到了01分数规划但最终还是看了题解 二分完后的点分治,只需要维护一个由之前处理过的子树得出的$tb数组$,然后根据遍历每个当前的子树上的结点的深度来确定$tb数组$中的滑块. 因为分数规划要找的是$max$,BFS遍历当前结点的深度越来越大,这样滑块也是单调向右滑动,所以滑块里的最大值就应当用单调队列解决 #include<cstdio> #include<algorithm> #define read(x) x=ge

BZOJ 1758 Wc2010 重建计划 树的点分治+二分+单调队列

题目大意:给定一棵树,询问长度在[l,u]范围内的路径中边权的平均值的最大值 01分数规划,首先想到二分答案 既然是统计路径肯定是点分治 每次统计时我们要找有没有大于0的路径存在 那么对于一棵子树的每一个深度i记录一个路径权值和的最大值 然后在这棵子树之前的所有子树的深度可选范围就是[l-i,u-i] 这个窗口是不停滑动的 因此用单调队列维护最大值即可 ↑上面这些网上的题解都说的还是蛮详细的 据说二分套在树分治里面会快一些 但是 尼玛 我被卡常了!! 这里只提供一些剪枝 1.当前分治的总点数<=

bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check

[Wc2010]重建计划 Time Limit: 40 Sec  Memory Limit: 162 MBSubmit: 4345  Solved: 1054[Submit][Status][Discuss] Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai,Bi,Vi分别表示道路(Ai,Bi),其价值为Vi 其中城市由1..N

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3