• 【BZOJ4712】洪水


    题解:

    注意题目说了每个点的权值只能增加

    每个点的dp方程比较简单 min(v[i],sum[i])

    那么我们考虑如果v[i]增加那么上面使用sum[i]的会带来影响

    暴力的做就是一个个往上查然后修改

    比较显然的是这个东西可以二分

    我们维护v[i]-sum[i]的值,查到那个不符合的就可以了

    这样我们就变成了花log^2n的时间对v[i]>sum[i]的变成v[i]<sum[i]

    而每次操作最多增加一个v[i]>sum[i]

    所以复杂度是对的

    树链剖分维护,复杂度nlog^2n

    还是比较考验代码能力的

    树剖那里一定要理清楚思路

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define rint register ll
    #define rll register ll
    #define IL inline
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--) 
    const ll N=2e5+1e4;
    const ll N2=N*4;
    const ll INF=1e9;
    ll n,m,v[N],head[N],id[N],rel[N],yz[N],fa[N],f[N],son[N],g[N],num[N],top[N],l;
    ll data[N2],cnt,lazy[N2];
    struct re{
      ll a,b,c;
    }e[N*2];
    void arr(ll x,ll y)
    {
      e[++l].a=head[x];
      e[l].b=y;
      head[x]=l;
    }
    void dfs(ll x,ll y)
    {
      f[x]=v[x]; num[x]=1; fa[x]=y;
      ll sum=0;
      for (rint u=head[x];u;u=e[u].a)
      {
        rint v=e[u].b;
        if (v!=y)
        { 
          yz[x]=1;
          dfs(v,x);
          sum+=f[v];
          num[x]+=num[v];
          if (num[v]>num[son[x]]) son[x]=v;
        }
      }
      if (sum) f[x]=min(f[x],sum);
      if (sum) g[x]=sum; else g[x]=f[x];
    }
    void dfs2(ll x,ll y,ll z)
    {
      id[x]=++cnt; rel[cnt]=x;
      top[x]=y;
      if (!son[x]) return;
      dfs2(son[x],y,x);
      for (rint u=head[x];u;u=e[u].a)
      {
        rint v=e[u].b;
        if (v!=z&&v!=son[x])  dfs2(v,v,x); 
      }
    }
    #define updata(x) data[x]=min(data[x*2],data[x*2+1])
    #define mid ((h+t)/2)
    IL void down(ll x)
    {
      if (!lazy[x]) return;
      lazy[x*2]+=lazy[x]; lazy[x*2+1]+=lazy[x];
      data[x*2]-=lazy[x]; data[x*2+1]-=lazy[x];
      lazy[x]=0; 
    }
    void build(ll x,ll h,ll t)
    {
      if (h==t) 
      {
        data[x]=v[rel[h]]-g[rel[h]];
        return;
      }
      build(x*2,h,mid); build(x*2+1,mid+1,t);
      updata(x);
    }
    ll query(ll x,ll h,ll t,ll pos)
    {
      if (h==t)
      {
        if (data[x]>0) return(v[rel[h]]-data[x]);
        else return(v[rel[h]]); 
      }
      down(x);
      if (pos<=mid) return(query(x*2,h,mid,pos));
      else return(query(x*2+1,mid+1,t,pos));
      updata(x);
    }
    void change2(ll x,ll h,ll t,ll h1,ll t1,ll k)
    {
      if (h1<=h&&t<=t1)
      {
        lazy[x]+=k; data[x]-=k; return;
      }
      down(x);
      if (h1<=mid) change2(x*2,h,mid,h1,t1,k);
      if (mid<t1) change2(x*2+1,mid+1,t,h1,t1,k);
      updata(x);
    }
    ll query2(ll x,ll h,ll t,ll h1,ll t1)
    {
      if (h1<=h&&t<=t1)
      {
        return(data[x]);
      }
      down(x);
      ll ans=INF;
      if (h1<=mid) ans=min(ans,query2(x*2,h,mid,h1,t1));
      if (mid<t1) ans=min(ans,query2(x*2+1,mid+1,t,h1,t1));
      return(ans);
    }
    vector<re> ve;
    void find2(ll x,ll h,ll t,ll h1,ll t1)
    {
      if (h1<=h&&t<=t1) 
      {
        ve.push_back((re){x,h,t}); return;
      }
      down(x);
      if (h1<=mid) find2(x*2,h,mid,h1,t1);
      if (mid<t1) find2(x*2+1,mid+1,t,h1,t1);
    }
    ll find3(ll x,ll h,ll t,ll k)
    {
      if (h==t) return(h);
      down(x);
      if (data[x*2+1]<k) return(find3(x*2+1,mid+1,t,k));
      else return(find3(x*2,h,mid,k)); 
    }
    void change(rll x,rll y)
    {
      if (!y) return;
      rll now=x;
      while (top[now])
      {
        if (query2(1,1,n,id[top[now]],id[now])>=y)
        {
          change2(1,1,n,id[top[now]],id[now],y); //v[x]-g[x] 减小y 
        } else
        {
          ve.clear();
          find2(1,1,n,id[top[now]],id[now]);
          rll l=int(ve.size())-1;
          rll k;
          dep(i,l,0)
            if (data[ve[i].a]<y)
            {
               k=find3(ve[i].a,ve[i].b,ve[i].c,y); // k.a 位置 k.b v[x]-g[x]
              break; 
            }
          rll x1=query(1,1,n,k);
          change2(1,1,n,k,id[now],y);
          rll x2=query(1,1,n,k);
          change(fa[rel[k]],x2-x1);
          break;
        }
        now=fa[top[now]];
      }
    }
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      ios::sync_with_stdio(false);
      cin>>n;
      rep(i,1,n) cin>>v[i];
      rep(i,1,n-1)
      {
        ll x,y; cin>>x>>y;
        arr(x,y); arr(y,x);
      }
      dfs(1,0); 
      dfs2(1,1,0);
      build(1,1,n);
      cin>>m;
      char cc;
      rep(i,1,m)
      {
        ll x,y;
        cin>>cc;
        if (cc=='Q')
        {
          cin>>x;
          cout<<query(1,1,n,id[x])<<endl;
        } else
        {
          cin>>x>>y;
          ll x1=query(1,1,n,id[x]);
          v[x]+=y;
          if (yz[x])
          { 
            change2(1,1,n,id[x],id[x],-y);
            ll x3=query(1,1,n,id[x]);
            if (x3>x1) change(fa[x],x3-x1);
          }
          else change(fa[x],y);
        }
      }
      return 0;
    }
  • 相关阅读:
    Linux上统计文件夹下文件个数
    linux----tail 过滤日志文件中的关键字
    Linux----Makefile
    Python--day 3
    Python--day 2
    Python--day 1
    Ubuntu14.04 64位网易云播放器
    qt 串口通信学习的目录
    qt layout 注意要点
    模拟电子第一章半导体
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9562048.html
Copyright © 2020-2023  润新知