zoukankan      html  css  js  c++  java
  • bzoj 3999: [TJOI2015]旅游

    Description

    为了提高智商,ZJY准备去往一个新世界去旅游。这个世界的城市布局像一棵树。每两座城市之间只有一条路径可
    以互达。每座城市都有一种宝石,有一定的价格。ZJY为了赚取最高利益,她会选择从A城市买入再转手卖到B城市
    。由于ZJY买宝石时经常卖萌,因而凡是ZJY路过的城市,这座城市的宝石价格会上涨。让我们来算算ZJY旅游完之
    后能够赚取的最大利润。(如a城市宝石价格为v,则ZJY出售价格也为v)

    Input

    第一行输入一个正整数N,表示城市个数。
    接下来一行输入N个正整数表示每座城市宝石的最初价格p,每个宝石的初始价格不超过100。
    第三行开始连续输入N-1行,每行有两个数字x和y。表示x城市和y城市有一条路径。城市编号从1开始。
    下一行输入一个整数Q,表示询问次数。
    接下来Q行,每行输入三个正整数a,b,v,表示ZJY从a旅游到b,城市宝石上涨v。
    1≤ N≤50000, 1≤Q ≤50000
     

    Output

     对于每次询问,输出ZJY可能获得的最大利润,如果亏本则输出0。

     

    Sample Input

    3
    1 2 3
    1 2
    2 3
    2
    1 2 100
    1 3 100

    Sample Output

    1
    1

    HINT

     

    Source

    省选前写的没发

    题意:给定一个有nn个节点的树,每个点又点权vivi,每次选取一条树链[a,b],求出max(vjvi),其中i,j[a,b]i,j∈[a,b]且i出现在j前面,最后树链[a,b][a,b]上的点点权都加上v

    显然的链剖转为序列问题,但线段树打起来太操蛋了,所以我选择了打分块;

    由于要满足i出现在j的前面,所以我们必须按照路径的顺序来处理,所以跳lca的时候要把路径存下来,并且终点到lca的路径要逆序处理,所以代码很冗长。

    具体做法的话就是:

    对于路径按顺序一直维护一个最小值,由于按照顺序处理,所以保证了i在j前面

    对于散点就直接与最小值做差比较,并更新最小值

    对于整块,就为维护一个整块内的最大值,最小值,和这一个块单独能产生的最大贡献;

    获益的话再与(最大值-不算这个块的最小值)和(这个块的单独贡献)取max;

    然后用块内最小值更新最小值

    更改暴力重构即可

    nlog*sqrt(n);卡时过的

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define int long long
    using namespace std;
    const int N=200050;
    const int Inf=(1ll<<60);
    int gi(){
        int x=0;
        char ch=getchar();
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
    int cnt,head[N],to[N],nxt[N],top[N],son[N],size[N],fa[N],deep[N],dfn[N],id[N],ed[N],v[N];
    int block,pos[N],L[N],R[N],MAX[N],MIN[N],MAXV[N],tot,tot2,tt,sum,add[N];
    int MAX2[N],MIN2[N],MAXV2[N];
    int minn,maxv;
    struct data{
        int l,r;
    }q[N],q2[N];
    bool cmp1(data a,data b){return a.r>b.r;}
    bool cmp2(data a,data b){return a.r<b.r;}
    inline int Min(int a,int b){
        return a<b?a:b;
    }
      
    inline int Max(int a,int b){
        return a>b?a:b;
    }
    inline void dfs1(RG int x,RG int f){
       deep[x]=deep[f]+1;size[x]=1;
       for(RG int i=head[x];i;i=nxt[i]){
          int y=to[i];
          if(y!=f){
         fa[y]=x;dfs1(y,x);
         size[x]+=size[y];
         if(size[y]>size[son[x]]) son[x]=y;  
          }
       }
    }
    inline void dfs2(RG int x,RG int f){
       dfn[x]=++sum;id[sum]=x;top[x]=f;
       if(son[x]) dfs2(son[x],f);
       for(RG int i=head[x];i;i=nxt[i]){
          int y=to[i];
          if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
       }
    }
    inline int lca(RG int x,RG int y){
       tot=0;int fl=1;
       while(top[x]!=top[y]){
          if(deep[top[x]]<deep[top[y]]) swap(x,y),fl^=1;
          if(fl) q[++tot]=(data){dfn[top[x]],dfn[x]};
          else q2[++tot2]=(data){dfn[top[x]],dfn[x]};
          x=fa[top[x]];
       }
       if(deep[x]<deep[y]) swap(x,y),fl^=1;
       if(fl) q[++tot]=(data){dfn[y],dfn[x]};
       else q2[++tot2]=(data){dfn[y],dfn[x]};
       return y;
    }
    inline void lnk(RG int x,RG int y){
        to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
        to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;
    }
    inline void rebuild(RG int i){
            MAX[i]=v[id[L[i]]],MIN[i]=v[id[L[i]]],MAXV[i]=0;
            for(RG int j=L[i]+1;j<=R[i];j++){
                MAXV[i]=Max(MAXV[i],v[id[j]]-MIN[i]);
                MAX[i]=Max(MAX[i],v[id[j]]);MIN[i]=Min(MIN[i],v[id[j]]);
            }
            MAX2[i]=MAX[i],MIN2[i]=v[id[R[i]]],MAXV2[i]=0;
            for(RG int j=R[i]-1;j>=L[i];j--){
                MAXV2[i]=Max(MAXV2[i],v[id[j]]-MIN2[i]);
                MIN2[i]=Min(MIN2[i],v[id[j]]);
            }
    }
    inline void update(RG int l,RG int r,RG int c){
        if(pos[l]==pos[r]){
            for(int i=l;i<=r;i++) v[id[i]]+=c;
            rebuild(pos[l]);
        }
        else{
            for(RG int i=l;i<=R[pos[l]];i++) v[id[i]]+=c;
            rebuild(pos[l]);
            for(RG int i=pos[l]+1;i<=pos[r]-1;i++) add[i]+=c;
            for(RG int i=L[pos[r]];i<=r;i++) v[id[i]]+=c;
            rebuild(pos[r]);
      }
    }
    inline void query(RG int l,RG int r){
        if(pos[l]==pos[r]){
            for(RG int i=l;i<=r;i++){
                maxv=Max(maxv,v[id[i]]+add[pos[l]]-minn);
                minn=Min(minn,v[id[i]]+add[pos[l]]);
            }
        }
        else{
            for(RG int i=l;i<=R[pos[l]];i++){
                maxv=Max(maxv,v[id[i]]+add[pos[l]]-minn);
                minn=Min(minn,v[id[i]]+add[pos[l]]);
            }
            for(RG int i=pos[l]+1;i<=pos[r]-1;i++){
                maxv=Max(maxv,max(MAX[i]+add[i]-minn,MAXV[i]));
                minn=Min(minn,MIN[i]+add[i]);
            }
            for(RG int i=L[pos[r]];i<=r;i++){
                maxv=Max(maxv,v[id[i]]+add[pos[r]]-minn);
                minn=Min(minn,v[id[i]]+add[pos[r]]);
            }
        }
    }
    inline void query2(RG int r,RG int l){
        if(pos[l]==pos[r]){
            for(RG int i=r;i>=l;i--){
                maxv=Max(maxv,v[id[i]]+add[pos[l]]-minn);
                minn=Min(minn,v[id[i]]+add[pos[l]]);
            }
        }
        else{
            for(RG int i=r;i>=L[pos[r]];i--){
                maxv=Max(maxv,v[id[i]]+add[pos[r]]-minn);
                minn=Min(minn,v[id[i]]+add[pos[r]]);
            }
            for(RG int i=pos[r]-1;i>=pos[l]+1;i--){
                maxv=Max(maxv,Max(MAX2[i]+add[i]-minn,MAXV2[i]));
                minn=Min(minn,MIN2[i]+add[i]);
            }
            for(RG int i=R[pos[l]];i>=l;i--){
                maxv=Max(maxv,v[id[i]]+add[pos[l]]-minn);
                minn=Min(minn,v[id[i]]+add[pos[l]]);
            }
        }
    }
    main()
    {
        int n=gi();for(int i=1;i<=n;i++) v[i]=gi();
        for(RG int i=1;i<n;i++){
            int x=gi(),y=gi();lnk(x,y);
        }
        dfs1(1,0);dfs2(1,1);
        block=sqrt(n);sum=n/block;
        if(n%block) sum++;
        for(RG int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
        for(RG int i=1;i<=sum;i++) L[i]=(i-1)*block+1,R[i]=i*block;
        R[sum]=n;
        for(RG int i=1;i<=sum;i++){
            MAX[i]=v[id[L[i]]],MIN[i]=v[id[L[i]]];
            for(RG int j=L[i]+1;j<=R[i];j++){
                MAXV[i]=Max(MAXV[i],v[id[j]]-MIN[i]);
                MAX[i]=Max(MAX[i],v[id[j]]);MIN[i]=Min(MIN[i],v[id[j]]);
            }
            MAX2[i]=v[id[R[i]]],MIN2[i]=v[id[R[i]]];
            for(RG int j=R[i]-1;j>=L[i];j--){
                MAXV2[i]=Max(MAXV2[i],v[id[j]]-MIN2[i]);
                MAX2[i]=Max(MAX2[i],v[id[j]]);MIN2[i]=Min(MIN2[i],v[id[j]]);
            }
        }
        int Q=gi();
        for(RG int i=1;i<=Q;i++){
            int a=gi(),b=gi(),c=gi();
            tot=0,tot2=0;lca(a,b);
            minn=Inf,maxv=-Inf;
            for(RG int j=1;j<=tot;j++) query2(q[j].r,q[j].l);
            for(RG int j=tot2;j>=1;j--) query(q2[j].l,q2[j].r);
            for(RG int j=1;j<=tot;j++) update(q[j].l,q[j].r,c);
            for(RG int j=1;j<=tot2;j++) update(q2[j].l,q2[j].r,c);
            if(maxv<0) puts("0");
            else printf("%lld
    ",maxv); 
        }
        return 0;
    }
    
    

      

  • 相关阅读:
    大数据培训:分享大数据行业就业趋势
    大数据培训:Zookeeper集群管理与选举
    【编码】UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position XXX
    MVC 登录后重定向回最初请求的 URL FormsAuthentication.RedirectFromLoginPage
    EasyUI 下载与引用
    EntityFrameWork Parameter '@columnType' must be defined.
    Hello World
    protobuf windows java 环境搭建
    android XML转义字符
    shiro Remember 1.2.4反序列化漏洞
  • 原文地址:https://www.cnblogs.com/qt666/p/6849589.html
Copyright © 2011-2022 走看看