LCA+二分+树上差分——Luogu2680 [NOIP2015]运输计划
2017-10-03 22:49
555 查看
题面:luogu2680
真受不了。。。这么多人AC的一道题目又花了我一个晚上时间做QAQ
所以这种题目就是近年来NOIP压轴题(也不一定是压轴题)的命题趋势?
13年的货车运输,15年的运输计划,16年的天天爱跑步,所以17年会是啥?
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/23/5e3c106c4f97b26d012a479990e3fc7f)
如果是这样,NOIP考场上这种题我还能在考试时间内切掉么?
简要思路:
首先我们肯定要求的给出的计划的LCA和距离啦(这个随便你怎么求)
接下来我们二分这个答案T,首先我们把距离>T的路径找出来,把这条路径上每条边都加上1。然后去找边权最大的被所有>T的路径覆盖的边,如果所有路径的距离最大值减去这条边的边权,那么这个答案T就是可行的,区间缩小即可。
为什么呢?因为如果想要所有距离小于T,那些比T大的计划都需要经过虫洞(显然)。所以我们就去找这些能让所有>T的路径都经过的边来作为虫洞。当然啦,我们肯定是贪心地找到边权最大的那条边并使之成为虫洞,这样节省的时间最多。
我的具体做法:
LCA的求法我用了树链剖分(因为边有边权,其实直接倍增更方便,也更快)。对于找那条神奇的边,我一开始也是想用树剖去找,但是复杂度貌似是O(nlog3n),30W的数据不能接受。所以还是树上差分靠谱些
然后调啊调终于AC了
哎呀~
其实我之前看到这种脑洞+码量题的时候都已经慌掉了,事实证明看到这种题不能慌,越慌越打不出来。像这种题只要想好思路之后仔细写下去就不会有什么大问题,注意细节就可以把这种题切掉了;
还有,要相信NOIP的数据不会强到哪里去,即使标算一时调不出来,差不多对的程序交上去,也可以骗到很多很多的分。我一开始这题差分打错还有65分就是一个蛮好的证明了。
真受不了。。。这么多人AC的一道题目又花了我一个晚上时间做QAQ
所以这种题目就是近年来NOIP压轴题(也不一定是压轴题)的命题趋势?
13年的货车运输,15年的运输计划,16年的天天爱跑步,所以17年会是啥?
如果是这样,NOIP考场上这种题我还能在考试时间内切掉么?
简要思路:
首先我们肯定要求的给出的计划的LCA和距离啦(这个随便你怎么求)
接下来我们二分这个答案T,首先我们把距离>T的路径找出来,把这条路径上每条边都加上1。然后去找边权最大的被所有>T的路径覆盖的边,如果所有路径的距离最大值减去这条边的边权,那么这个答案T就是可行的,区间缩小即可。
为什么呢?因为如果想要所有距离小于T,那些比T大的计划都需要经过虫洞(显然)。所以我们就去找这些能让所有>T的路径都经过的边来作为虫洞。当然啦,我们肯定是贪心地找到边权最大的那条边并使之成为虫洞,这样节省的时间最多。
我的具体做法:
LCA的求法我用了树链剖分(因为边有边权,其实直接倍增更方便,也更快)。对于找那条神奇的边,我一开始也是想用树剖去找,但是复杂度貌似是O(nlog3n),30W的数据不能接受。所以还是树上差分靠谱些
然后调啊调终于AC了
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <iostream> #include <ctime> #include <map> #include <queue> #include <cstdlib> #include <string> #include <climits> #include <set> #include <vector> using namespace std; inline int read(){ int k=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();} return k*f; } struct ppap{int x,y,l,lca;}a[300010]; int nedge=0,p[600010],c[600010],nex[600010],head[600010]; int n,m,s[300010],son[300010],cnt=0,cj[300010],maxx=0,Cnt,Maxx; int deep[300010],top[300010],fa[300010],sx[300010]; int f[300010],add[300010]; inline void sadd(int x,int y){for(;x<=n;x+=x&-x)f[x]+=y;} inline int slca(int x){int ans=0;for(;x;x-=x&-x)ans+=f[x];return ans;}//用来优化常数的树状数组 inline void addedge(int x,int y,int z){ p[++nedge]=y;c[nedge]=z;nex[nedge]=head[x];head[x]=nedge; } inline void dfs(int x,int fat,int dep){ deep[x]=dep;fa[x]=fat;s[x]=1; for(int k=head[x];k;k=nex[k])if(p[k]!=fat){ dfs(p[k],x,dep+1);s[x]+=s[p[k]];cj[p[k]]=c[k]; if(s[son[x]]<s[p[k]])son[x]=p[k]; } } inline void dfss(int x,int t){ sx[x]=++cnt;top[x]=t; if(son[x])dfss(son[x],t); for(int k=head[x];k;k=nex[k])if(p[k]!=fa[x]&&p[k]!=son[x])dfss(p[k],p[k]); } inline void flca(int i){ int x=a[i].x,y=a[i].y; int fx=top[x],fy=top[y],ans=0; while(fx!=fy){ if(deep[fx]<deep[fy])swap(fx,fy),swap(x,y); ans+=slca(sx[x])-slca(sx[fx]-1);x=fa[fx];fx=top[x]; } if(deep[x]>deep[y])swap(x,y); ans+=slca(sx[y])-slca(sx[x]); a[i].l=ans;a[i].lca=x; }//链剖求LCA和距离 inline void DFS(int x){ for(int k=head[x];k;k=nex[k])if(p[k]!=fa[x]){ DFS(p[k]);add[x]+=add[p[k]]; } if(add[x]==Cnt)Maxx=max(Maxx,cj[x]); } inline bool check(int x){ Cnt=0;memset(add,0,sizeof add); for(int i=1;i<=m;i++)if(a[i].l>x){ Cnt++;add[a[i].lca]-=2;add[a[i].x]++;add[a[i].y]++;//差分 } Maxx=0;DFS(1);//DFS是验证 return maxx-Maxx<=x; } int main() { n=read();m=read(); for(int i=1;i<n;i++){ int x=read(),y=read(),z=read(); addedge(x,y,z);addedge(y,x,z); } dfs(1,0,1);dfss(1,1); for(int i=1;i<=n;i++)sadd(sx[i],cj[i]); maxx=0; for(int i=1;i<=m;i++){ a[i].x=read();a[i].y=read();flca(i); maxx=max(maxx,a[i].l); } int l=0,r=maxx,ans=maxx; while(l<=r){ int mid=l+r>>1; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } printf("%d",ans); return 0; }
哎呀~
其实我之前看到这种脑洞+码量题的时候都已经慌掉了,事实证明看到这种题不能慌,越慌越打不出来。像这种题只要想好思路之后仔细写下去就不会有什么大问题,注意细节就可以把这种题切掉了;
还有,要相信NOIP的数据不会强到哪里去,即使标算一时调不出来,差不多对的程序交上去,也可以骗到很多很多的分。我一开始这题差分打错还有65分就是一个蛮好的证明了。
相关文章推荐
- 【BZOJ】4326 NOIP2015 运输计划 二分+LCA+树上差分
- LuoguP2680/UOJ150[NOIP2015] 运输计划 解题报告【二分答案+树上操作(LCA)+树上差分】
- NOIP2015 运输计划 二分答案+Tarjan LCA+树上差分
- [BZOJ4326][NOIP2015]运输计划(二分+dfs序+树上差分)
- 【NOIP2015】运输计划 {二分答案+倍增+树上差分}
- BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)
- bzoj 4326: NOIP2015 运输计划【树链剖分+二分+树上差分】
- 洛谷 2680[NOIP2015] 运输计划 二分+lca+树上差分+dfs序
- Noip2015 运输计划 【二分答案】【差分】【LCA】
- [BZOJ4326][NOIP2015]运输计划(二分答案+树上差分)
- NOIP 2015 Day2 T3 运输计划(二分+dfs序+树上差分+倍增LCA)
- NOIP2015 运输计划 (树链剖分,LCA,树上差分)
- 【uoj#150】【NOIP2015】运输计划 树上前缀和+lca+二分+拓扑排序+特别的卡常数技巧
- bzoj4326 & UOJ150【NOIP2015】运输计划 ( 树上差分 + lca )
- BZOJ 4326: NOIP2015 运输计划【LCA】【二分】【差分】
- Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)
- 【NOIP2015】运输计划(树上差分,二分答案)
- bzoj4326【2015提高】运输计划(二分答案+lca+树上差分前缀和)
- [BZOJ4326][NOIP2015]运输计划(二分+dfs序+树上差分)
- BZOJ 4326: NOIP2015 运输计划 二分答案 树上差分