【BZOJ2500】幸福的道路 树形DP+RMQ+双指针法
生活随笔
收集整理的這篇文章主要介紹了
【BZOJ2500】幸福的道路 树形DP+RMQ+双指针法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【BZOJ2500】幸福的道路
Description
小T與小L終于決定走在一起,他們不想浪費在一起的每一分每一秒,所以他們決定每天早上一同晨練來享受在一起的時光. 他們畫出了晨練路線的草圖,眼尖的小T發(fā)現可以用樹來描繪這個草圖. 他們不愿枯燥的每天從同一個地方開始他們的鍛煉,所以他們準備給起點標號后順序地從每個起點開始(第一天從起點一開始,第二天從起點二開始……). 而且他們給每條道路定上一個幸福的值.很顯然他們每次出發(fā)都想走幸福值和最長的路線(即從起點到樹上的某一點路徑中最長的一條). 他們不愿再經歷之前的大起大落,所以決定連續(xù)幾天的幸福值波動不能超過M(即一段連續(xù)的區(qū)間并且區(qū)間的最大值最小值之差不超過M).他們想知道要是這樣的話他們最多能連續(xù)鍛煉多少天(hint:不一定從第一天一直開始連續(xù)鍛煉)? 現在,他們把這個艱巨的任務交給你了!Input
第一行包含兩個整數N, M(M<=10^9). 第二至第N行,每行兩個數字Fi , Di, 第i行表示第i個節(jié)點的父親是Fi,且道路的幸福值是Di.Output
最長的連續(xù)鍛煉天數Sample Input
3 21 1
1 3
Sample Output
3數據范圍:
50%的數據N<=1000
80%的數據N<=100 000
100%的數據N<=1000 000
題解:這題顯然可以被分成兩個子任務
1.求樹上距離點i最遠的點到i的距離
方法:維護每個點子樹中到這個點距離的最大值和次大值,然后搞一搞~
2.求最長的一段區(qū)間,使得區(qū)間中最大值和最小值的差≤M
方法:先用RMQ求出區(qū)間最大值最小值,然后上雙指針法
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn=1000010; int n,m,cnt,l,r,ans; int fa[maxn],to[maxn<<1],next[maxn<<1],head[maxn]; int d1[maxn],d2[maxn],q[maxn],from[maxn]; int Log[maxn],dm[maxn][20],dn[maxn][20]; void updata(int x,int tmp) {if(d1[x]<tmp) d2[x]=d1[x],d1[x]=tmp;else d2[x]=max(d2[x],tmp); } void dfs1(int x) {int i,tmp;q[++q[0]]=x;for(i=head[x];i!=-1;i=next[i])dfs1(to[i]),updata(x,d1[to[i]]+from[to[i]]); } void add(int a,int b) {to[cnt]=b;next[cnt]=head[a];head[a]=cnt++; } int gm(int a,int b) {int k=Log[b-a+1];return max(dm[a][k],dm[b-(1<<k)+1][k]); } int gn(int a,int b) {int k=Log[b-a+1];return min(dn[a][k],dn[b-(1<<k)+1][k]); } int main() {scanf("%d%d",&n,&m);int i,j,a,b,c;memset(head,-1,sizeof(head));for(i=2;i<=n;i++){scanf("%d%d",&fa[i],&from[i]);add(fa[i],i);}dfs1(1);for(i=2;i<=n;i++){if(d1[fa[q[i]]]==d1[q[i]]+from[q[i]]) updata(q[i],d2[fa[q[i]]]+from[q[i]]);else updata(q[i],d1[fa[q[i]]]+from[q[i]]);}for(i=1;i<=n;i++) dm[i][0]=dn[i][0]=d1[i];for(i=2;i<=n;i++) Log[i]=Log[i>>1]+1;for(j=1;(1<<j)<=n;j++){for(i=1;i+(1<<j)-1<=n;i++){dm[i][j]=max(dm[i][j-1],dm[i+(1<<j-1)][j-1]);dn[i][j]=min(dn[i][j-1],dn[i+(1<<j-1)][j-1]);}}int h=1;ans=-1;for(i=1;i<=n;i++){while(gm(h,i)-gn(h,i)>m) h++;ans=max(ans,i-h+1);}printf("%d",ans);return 0; }轉載于:https://www.cnblogs.com/CQzhangyu/p/6819604.html
總結
以上是生活随笔為你收集整理的【BZOJ2500】幸福的道路 树形DP+RMQ+双指针法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: docker命令收集
- 下一篇: 月度开销