NOIP2015 运输计划
来源:互联网 发布:印度数学网络课程 编辑:程序博客网 时间:2024/06/11 15:23
Problem
既然是NOIP的题目,那么…… 意料之中的偷懒不可避免
Solution
Actually,刚开始看这道题目的时候没有什么想法,然后就手贱点开了标签——树链剖分!!!
于是我果断就怂了,过了几天,我现在又才继续写,发现好像也不一定需要树链剖分,不过树链剖分比较好写吧可能。树链剖分我只是看了看,也没有实现了,好像就是将树分成几条链,这样就可以在链上用线段树快速维护出需要的信息。当然,我还是先不谈论这种高深的话题了。
如果等我学了树链剖分之后,我还记得这件事的话,我就填坑。
首先,我们发现可以枚举这个最短距离k,而且还可以二分答案。我经过卡评测之后发现maxr设到
其次为了好查询距离,我们可以记录每个节点到根节点的距离,再记录每组运输计划两节点的公共祖先,然后就可以利用
所以关键问题就在于如何快速求这个公共交点。对于一个距离超过k的运输计划x->y,记录路径对节点的覆盖次数,利用差分快速修改,
貌似这道题还需要一点卡常技巧,我也不知道考NOIP的时候,能不能卡进去,但至少交到OJ上A了。
Code
#include <algorithm>#include <iostream>#include <cstring>#include <cstdio>using namespace std;const int size=300010,maxr=200000000;struct data{ int v,w,nxt;}edge[size<<1];int n,m,p,head[size],deep[size],pre[size][21];int s[size],t[size],lca[size],cha[size],sum[size];template <typename Tp> inline void read(Tp &x){ x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();}inline int max(int x,int y){return x>y?x:y;}inline void insert(int u,int v,int w){ edge[++p].v=v;edge[p].w=w; edge[p].nxt=head[u];head[u]=p; edge[++p].v=u;edge[p].w=w; edge[p].nxt=head[v];head[v]=p;}void dfs(int x,int fa){ for(int i=1;i<=20;i++) pre[x][i]=pre[pre[x][i-1]][i-1]; for(int i=head[x];i;i=edge[i].nxt) if(edge[i].v!=fa) { deep[edge[i].v]=deep[x]+1; pre[edge[i].v][0]=x; sum[edge[i].v]=sum[x]+edge[i].w; dfs(edge[i].v,x); }}int getlca(int x,int y){ if(deep[x]>deep[y]) swap(x,y); int t=deep[y]-deep[x]; for(int i=20;i>=0;i--) if(t&(1<<i)) y=pre[y][i]; if(x==y) return x; for(int i=20;i>=0;i--) if(pre[x][i]!=pre[y][i]) x=pre[x][i],y=pre[y][i]; return pre[x][0];}void input(){ int tu,tv,tw; read(n),read(m); for(int i=1;i<n;i++) { read(tu),read(tv),read(tw); insert(tu,tv,tw); } dfs(1,0); for(int i=1;i<=m;i++) { read(s[i]),read(t[i]); lca[i]=getlca(s[i],t[i]); }}void update(int x,int fa){ for(int i=head[x];i;i=edge[i].nxt) if(edge[i].v!=fa) { update(edge[i].v,x); cha[x]+=cha[edge[i].v]; }}bool check(int k){ memset(cha,0,sizeof(cha)); int num=0,maxn=0,maxdis=0; for(int i=1;i<=m;i++) if(sum[s[i]]+sum[t[i]]-2*sum[lca[i]]>k) { num++; maxdis=max(maxdis,sum[s[i]]+sum[t[i]]-2*sum[lca[i]]); cha[s[i]]++,cha[t[i]]++,cha[lca[i]]-=2; } update(1,0); for(int i=2;i<=n;i++) if(cha[i]>=num) maxn=max(maxn,sum[i]-sum[pre[i][0]]); if(maxdis-maxn>k) return false; return true;}int main(){ int l=0,r=maxr,m; input(); while(l<r) { m=(l+r)>>1; if(check(m)) r=m; else l=m+1; } printf("%d\n",l); return 0;}
- 【NOIP2015】【BZOJ4326】运输计划
- [bzoj4326][NOIP2015]运输计划
- NOIP2015 运输计划
- NOIP2015 day2t3 运输计划
- NOIP2015运输计划 题解
- noip2015 运输计划
- codevs4632: [NOIP2015]运输计划
- NOIP2015 D2T3运输计划
- noip2015运输计划
- 【NOIP2015】Day2T3 运输计划
- NOIP2015运输计划
- [NOIP2015]运输计划
- NOIP2015 运输计划
- NOIP2015 day2t3 运输计划
- 4326: NOIP2015 运输计划
- noip2015 运输计划
- [bzoj4326]NOIP2015 运输计划
- bzoj4326 NOIP2015 运输计划
- MarkDown常用语法
- python笔记4
- 计算机的发展阶段
- Android开发基础知识回顾
- 我为什么选择产品经理
- NOIP2015 运输计划
- 个人总结19
- 不同路径-LintCode
- 携程的学习及使用
- Android Studio – Cannot resolve symbol ‘R’
- 机器学习系列二
- C++ 对指针的理解
- 代码优化
- python笔记5