POJ - 3162 Walking Race 【树上最远距离 + 线段树处理区间最值 + 尺取法 】
2017-10-13 11:14
253 查看
传送门
//一棵树, wc第i天从第i个节点开始跑, 记录一个最大值., 然后可以获得n个最大值, 然后从中选取连续的尽可能长的天数使得其中的最大值 - 最小值 <= m 问这个最大的天数是多少.
//思路: 每个点的最大值可由树的直径求出, 然后问题转变为给你一串数字, 从中选取最长的区间, 使得其中的最大最小值之差<=m, 所以处理区间问题当然是用线段树呀, 然后进行尺取, 双指针i,j, 一起往右移, 如果满足就让j++,否则就让i++, 然后一直尺取完即可
AC Code
//一棵树, wc第i天从第i个节点开始跑, 记录一个最大值., 然后可以获得n个最大值, 然后从中选取连续的尽可能长的天数使得其中的最大值 - 最小值 <= m 问这个最大的天数是多少.
//思路: 每个点的最大值可由树的直径求出, 然后问题转变为给你一串数字, 从中选取最长的区间, 使得其中的最大最小值之差<=m, 所以处理区间问题当然是用线段树呀, 然后进行尺取, 双指针i,j, 一起往右移, 如果满足就让j++,否则就让i++, 然后一直尺取完即可
AC Code
const int maxn = 1e6+5; int n,m; int dis1[maxn],dis2[maxn]; int cnt,head[maxn]; int a[maxn]; struct node { int to,w,next; }e[maxn*2]; void add(int u,int v,int w) { e[cnt] = (node){v,w,head[u]}; head[u] = cnt++; } int maxlen,st,ed; void dd(int u,int fa,int len,int flag) { if(flag) dis1[u] = len; else dis2[u] = len; if(len > maxlen && flag) st = u, maxlen = len; for(int i=head[u] ; ~i ; i=e[i].next){ int to = e[i].to; if(to == fa) continue; dd(to,u,len+e[i].w,flag); } } struct Tree { int tl,tr; int minn,maxx; }tree[maxn<<2]; int mi,mx; void pushup(int id) { tree[id].minn = min(tree[id<<1].minn , tree[id<<1|1].minn); tree[id].maxx = max(tree[id<<1].maxx , tree[id<<1|1].maxx); } void build(int l,int r,int id) { tree[id].tl = l, tree[id].tr = r; if(l == r){ tree[id].maxx = tree[id].minn = a[l]; //cout << a[l] << endl; return ; } int mid = (r+l)>>1; build(l,mid,id<<1); build(mid+1,r,id<<1|1); pushup(id); } void query(int ql,int qr,int id) { int l = tree[id].tl, r = tree[id].tr; if(ql <= l && qr >= r ){ mi = min(mi,tree[id].minn); mx = max(mx,tree[id].maxx); return ; } int mid = (l + r) >> 1; if(ql <= mid) query(ql,qr,id<<1); if(qr > mid) query(ql,qr,id<<1|1); } void solve() { while(~scanf("%d%d",&n,&m)){ cnt = 0; Fill(head,-1); for(int i=2;i<=n;i++){ int u,w; scanf("%d%d",&u,&w); add(u,i,w); add(i,u,w); } Fill(dis1,0); Fill(dis2,0); maxlen = -1; dd(1,-1,0,1); ed = st; maxlen = -1; dd(st,-1,0,1); swap(st,ed); dd(ed,-1,0,0); for(int i=1;i<=n;i++){ a[i] = max(dis1[i],dis2[i]); } build(1,n,1); int ans = 0; int i=1,j=2; while(i<=j && j<=n){ mi = inf,mx = 0; query(i,j,1); if(mx - mi <= m){ ans = max(ans,j-i+1); j++; } else i++; if(n - i + 1 <= ans) break; } printf("%d\n",ans); } }
相关文章推荐
- POJ-3162 Walking Race (求树上两点之间最大距离)
- POJ 3667 线段树 + 延迟标记 + 区间处理
- POJ 3162 Walking Race(树形dp+单调队列 or 线段树)
- 【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)
- poj 3162 walking race 树形dp 求符合条件区间
- POJ 3162 浅谈尺取法区间问题运用及多源树上路径统计
- POJ 3145Harmony Forever(线段树更新+分情况处理数据+区间极值查询+好题)
- POJ 3162 Walking Race (DFS + 线段树)
- 【树形DP】Poj 3162 Walking Race (DP_树形DP(线段树))
- poj 3225 Help with Intervals(线段树进阶,处理区间,拆点)
- POJ 3162 Walking Race (DFS + 线段树)
- POJ 3162 Walking Race 树的直径+线段树
- POJ 3162 Walking Race(单调队列或线段树加树型DP)
- (Relax 数论1.14)POJ 26889 Prime Distance(区间筛素数:求一个区间L\U中距离最近的两个素数和距离最远的两个素数)
- poj 3468 线段树(区间更新)模板题
- [POJ 2777]Count Color[线段树区间更新查询]
- POJ-1195 Mobile phones 二维线段树 区间求和
- poj 3162 Walking Race
- poj 3667 线段树(区间合并)
- Tallest Cow POJ - 3263(线段树区间修改,单点查询)