POJ

来源:互联网 发布:随机抽取名字软件 编辑:程序博客网 时间:2024/05/29 10:02

传送门
//一棵树, 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);    }}
原创粉丝点击