zoukankan      html  css  js  c++  java
  • hdu 4729 树链剖分

    思路:这个树链剖分其实还是比较明显的。将边按权值排序后插入线段树,然后用线段树查找区间中比某个数小的数和,以及这样的数的个数。当A<=B时,就全部建新的管子。

    对于A>B的情况比较 建一条由S->T的管子后将这根管子容量扩到最大能得到的容量  与   将所有预算都用来扩大管子容量不建新管子得到的最大容量 做比较 ,选最大的。

    扩容量能得到的最大权值可以同过二分枚举答案,用树链剖分判断。

    #include<set>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<string>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define pb push_back
    #define mp make_pair
    #define Maxn 200010
    #define Maxm 400010
    #define LL __int64
    #define Abs(x) ((x)>0?(x):(-x))
    #define lson(x) (x<<1)
    #define rson(x) (x<<1|1)
    #define inf 100000
    #define lowbit(x) (x&(-x))
    #define clr(x,y) memset(x,y,sizeof(x))
    #define Mod 1000000007
    using namespace std;
    int head[Maxn],vi[Maxn],dep[Maxn],w[Maxn],top[Maxn],son[Maxn],sz[Maxn],fa[Maxn],e,id;
    int val[Maxn];
    int num[Maxn],cnt;
    struct Point{
        int val,i;
        int operator <(const Point &temp) const{
            return val<temp.val;
        }
    }lis[Maxn];
    struct Edge{
        int u,v,next;
        int val;
    }edge[Maxn*3];
    struct Tree{
        int l,r,c;
        int *p;
        int *q;
        int mid(){
            return (l+r)>>1;
        }
    }tree[Maxn*3];
    void init()
    {
        clr(head,-1);clr(vi,0);
        e=0;id=0;
    }
    void add(int u,int v,int val)
    {
        edge[e].u=u,edge[e].v=v,edge[e].val=val,edge[e].next=head[u],head[u]=e++;
    }
    void BuildTree(int l,int r,int po)
    {
        tree[po].l=l,tree[po].r=r,tree[po].c=0;
        tree[po].p=new int[r-l+2];
        tree[po].q=new int[r-l+2];
        tree[po].q[0]=0;
        if(l==r)
            return ;
        int mid=tree[po].mid();
        BuildTree(l,mid,lson(po));
        BuildTree(mid+1,r,rson(po));
    }
    void update(int i,int c,int po)
    {
        if(tree[po].l==tree[po].r){
            tree[po].p[++tree[po].c]=c;
            tree[po].q[tree[po].c]=tree[po].q[tree[po].c-1]+c;
            return ;
        }
        tree[po].p[++tree[po].c]=c;
        tree[po].q[tree[po].c]=tree[po].q[tree[po].c-1]+c;
        int mid=tree[po].mid();
        if(i<=mid)
            update(i,c,lson(po));
        else
            update(i,c,rson(po));
    }
    int getmin(int l,int r,int po)
    {
        if(l<=tree[po].l&&tree[po].r<=r){
            return tree[po].p[1];
        }
        int mid=tree[po].mid();
        if(r<=mid)
            return getmin(l,r,lson(po));
        else if(l>=mid+1)
            return getmin(l,r,rson(po));
        else{
            return min(getmin(l,mid,lson(po)),getmin(mid+1,r,rson(po)));
        }
    }
    LL getans(int l,int r,LL val,int po)
    {
        if(l<=tree[po].l&&tree[po].r<=r){
            int pos=lower_bound(tree[po].p+1,tree[po].p+tree[po].c+1,val)-tree[po].p;
            if(pos>tree[po].c){
                cnt+=tree[po].c;
                return tree[po].q[tree[po].c];
            }
            if(pos>1){
                cnt+=pos-1;
                return tree[po].q[pos-1];
            }
            return 0;
        }
        int mid=tree[po].mid();
        if(r<=mid)
            return getans(l,r,val,lson(po));
        else if(l>=mid+1)
            return getans(l,r,val,rson(po));
        else{
            return getans(l,mid,val,lson(po))+getans(mid+1,r,val,rson(po));
        }
    }
    void dfs(int u,int val)
    {
        vi[u]=1;
        int i,v;
        son[u]=0,sz[u]=1;
        num[u]=val;
        for(i=head[u];i!=-1;i=edge[i].next){
            v=edge[i].v;
            if(vi[v]) continue;
            dep[v]=dep[u]+1;
            fa[v]=u;
            dfs(v,edge[i].val);
            if(sz[v]>sz[son[u]])son[u]=v;
            sz[u]+=sz[v];
        }
    }
    void build(int u,int ti)
    {
        int i,v;
        w[u]=++id;top[u]=ti;vi[u]=1;
        lis[id].i=id,lis[id].val=num[u];
        if(son[u]) build(son[u],ti);
        for(i=head[u];i!=-1;i=edge[i].next){
            v=edge[i].v;
            if(vi[v]||v==son[u]) continue;
            build(v,v);
        }
    }
    LL need(LL val,int u,int v)
    {
        int f1=top[u],f2=top[v];
        cnt=0;
        LL ans=0;
       // cout<<u<<" "<<f1<<" "<<v<<" "<<f2<<" "<<w[f1]<<" "<<w[u]<<endl;
        while(f1!=f2){
            if(dep[f1]<dep[f2]){
                swap(f1,f2),swap(u,v);
            }
            ans+=getans(w[f1],w[u],val,1);
            u=fa[f1];f1=top[u];
        }
        if(dep[u]>dep[v])
            swap(u,v);
        if(u!=v)
        ans+=getans(w[son[u]],w[v],val,1);
        //cout<<u<<" "<<v<<" "<<val<<" "<<cnt<<" "<<ans<<" "<<val*cnt-ans<<endl;
        ans=val*(LL)cnt-ans;
        return ans;
    }
    void calc(int u,int v,LL k,LL a,LL b)
    {
        int x=u,y=v;
        int f1=top[u],f2=top[v];
        LL ans=10000000;
        while(f1!=f2){
            if(dep[f1]<dep[f2]){
                swap(f1,f2),swap(u,v);
            }
            ans=min(ans,(LL)getmin(w[f1],w[u],1));
            u=fa[f1];f1=top[u];
        }
        if(dep[u]>dep[v])
            swap(u,v);
        if(u!=v)
        ans=min(ans,(LL)getmin(w[son[u]],w[v],1));
        LL capacity=0;
        if(k<min(a,b)){
            printf("%I64d
    ",ans);
            return ;
        }
        if(a<=b){
            printf("%I64d
    ",k/a+ans);
            return ;
        }
        if(k>=a)
        capacity=(k-a)/b+1+ans;
        LL l,r,mid,temp;
        l=0,r=k/b+ans+1;
        while(l+1<r){
            mid=(l+r)>>1;
            temp=need(mid,x,y);
            temp*=b;
            if(temp<=k)
                l=mid;
            else
                r=mid-1;
        }
        if(r>=1)
        if(need(r,x,y)*b<=k&&r>l)
            l=r;
        printf("%I64d
    ",max(capacity,l));
        return ;
    }
    int main()
    {
        int t,n,m,i,j,u,v,val,q,a,b,k,Case=0;
        scanf("%d",&t);
        while(t--){
            init();
            scanf("%d%d",&n,&m);
            for(i=1;i<n;i++){
                scanf("%d%d%d",&u,&v,&val);
                add(u,v,val);
                add(v,u,val);
            }
            dfs(1,1200000000);
            memset(vi,0,sizeof(vi));
            build(1,1);
            sort(lis+1,lis+id+1);
            BuildTree(1,n,1);
            for(i=1;i<=n;i++){
                update(lis[i].i,lis[i].val,1);
            }
            printf("Case #%d:
    ",++Case);
            for(i=1;i<=m;i++){
                scanf("%d%d%d%d%d",&u,&v,&k,&a,&b);
                calc(u,v,k,a,b);
            }
        }
        return 0;
    }
  • 相关阅读:
    jmeter使用指南:jmeter无脑式指南
    手机上传图片的一些小问题
    总结-Linux
    阿里云服务器Linux CentOS安装配置(11)安装Wordpress
    Linux服务器tomcat启动很慢
    微信小程序开发的游戏《拼图游戏》
    微信小程序弹出操作菜单
    微信小程序计算经纬距离
    java.lang.NoClassDefFoundError: com/sun/image/codec/jpeg/JPEGCodec
    微信昵称有特殊符号怎么保存到mysql库里?
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3325430.html
Copyright © 2011-2022 走看看