Hdu 6241 bisection + tree dp

This is the L question in Harbin. Just thinking about the two-point answer is very watery. After the total number is determined, each subtree has an interval, and the tree dp merges this interval. Once there is an empty interval, it is not enough. It should be noted that it is necessary to judge whether the maximum value of the root node can obtain a two-point answer.
Code:

#include <bits/stdc++.h>
using namespace std;
const int maxn=100007;
struct edge{
    int to, next;
}e[maxn*2];
int head[maxn];
int cnt;
void init(){
    cnt=0;
    memset(head, -1, sizeof(head));
}
void add(int u, int v){
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
int n, a[maxn], b[maxn];
long long mn[maxn], mx[maxn];
bool flag;
void dfs(int u, int fa){
    long long mnsum=0, mxsum=1;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].to;
        if(v==fa)continue;
        dfs(v, u);
        mnsum+=mn[v];
        mxsum+=mx[v];
    }
    mn[u]=max(mn[u], mnsum);
    mx[u]=min(mx[u], mxsum);
    if(mn[u]>mx[u])flag=false;
}
bool check(int mid){
    for(int i=1;i<=n;i++){
        mn[i]=a[i], mx[i]=mid-b[i];
        if(mn[i]>mx[i])return false;
    }
    flag=true;
    dfs(1, 0);
    if(mx[1]<mid)return false;
    //若无特判下面数据会跪
    //1
    //3
    //1 2
    //1 3
    //1
    //1 1
    //1
    //1 1
    return flag;
}
int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        init();
        scanf("%d", &n);
        for(int i=1;i<n;i++){
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }

        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));

        int q;
        scanf("%d", &q);
        for(int i=1;i<=q;i++){
            int id, num;
            scanf("%d%d", &id, &num);
            a[id]=max(a[id], num);
        }

        scanf("%d", &q);
        for(int i=1;i<=q;i++){
            int id, num;
            scanf("%d%d", &id, &num);
            b[id]=max(b[id], num);
        }

        if(!check(n)){
            printf("-1\n");
        }
        else {
            int l=0, r=n, tag=-1;
            while(l<=r){
                if(r-l<=1){
                    if(check(l))tag=l;
                    else tag=r;
                    break;
                }
                int mid=(l+r)/2;
                if(check(mid))r=mid;
                else l=mid;
            }
            printf("%d\n", tag);
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325945928&siteId=291194637