【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;
}

 

posted @ 2018-08-30 18:58  尹吴潇  阅读(164)  评论(0编辑  收藏  举报