• 【BZOJ3252】攻略


    题解:

    首先贪心的会发现我们每次一定会选当前权值和最大的那个

    然后在于怎么维护这个最大值

    我们发现每个修改实际上是对沿途所有点的子树的修改

    所以用线段树维护就可以了。。

    另外注意有重复部分,但一定是包含关系所以比较好处理

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define IL inline
    #define ll long long
    #define rint register ll
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    #define mid ((h+t)/2)
    char ss[1<<24],*A=ss,*B=ss;
    char gc()
    {
      return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
    }
    template<class T> void read(T &x)
    {
      rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=c^48;
      while (c=gc(),47<c&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; 
    }
    const ll INF=1e9;
    const ll N=3e5;
    ll n,m,k,l,v[N],head[N],maxn[N],minn[N],sum[N],fa[N],cnt,ans;
    struct re{
      ll a,b;
    }a[N];
    const ll N2=N*4;
    ll data1[N2],data2[N2],data3[N2],lazy1[N2],lazy2[N2],real2[N2];
    void arr(ll x,ll y)
    {
      a[++l].a=head[x];
      a[l].b=y;
      head[x]=l;
    }
    IL void down(ll x)
    {
      if (!lazy1[x]) return;
      lazy1[x*2]=lazy1[x*2+1]=lazy1[x];
      lazy2[x*2]+=lazy2[x];
      lazy2[x*2+1]+=lazy2[x];
      data3[x*2]+=lazy2[x]; data3[x*2+1]+=lazy2[x];
      data2[x*2]=lazy1[x]; data2[x*2+1]=lazy1[x];
      lazy1[x]=lazy2[x]=0;
    }
    IL void updata(ll x)
    {
      if (data3[x*2]<data3[x*2+1])
      {
        data2[x]=data2[x*2+1];
        data1[x]=data1[x*2+1];
        data3[x]=data3[x*2+1]; 
      } else
      {
        data2[x]=data2[x*2];
        data1[x]=data1[x*2];
        data3[x]=data3[x*2];
      }
    }
    void build(ll x,ll h,ll t)
    {
      if (h==t)
      {
        data1[x]=real2[h]; return;
      }
      build(x*2,h,mid); build(x*2+1,mid+1,t);
    }
    void change(ll x,ll h,ll t,ll h1,ll t1,ll k1,ll k2)
    {
      if (h1<=h&&t<=t1)
      {
        lazy1[x]=k1; lazy2[x]+=k2; data3[x]+=k2; data2[x]=k1;
        return;
      }
      down(x);
      if (h1<=mid) change(x*2,h,mid,h1,t1,k1,k2);
      if (mid<t1)  change(x*2+1,mid+1,t,h1,t1,k1,k2);
      updata(x);
    }
    void dfs1(ll x)
    {
      ll u=head[x];
      if (!u)
      {
        real2[++cnt]=x;
        return;
      }
      while (u)
      {
        ll vv=a[u].b;
        dfs1(vv);
        u=a[u].a;
      }
    }
    void dfs(ll x,ll y)
    {
      ll u=head[x]; sum[x]=y+v[x];
      if (!u)
      {
        minn[x]=maxn[x]=++cnt;
        real2[cnt]=x;
        change(1,1,n,cnt,cnt,0,sum[x]);
        return;
      }
      while (u)
      {
        ll vv=a[u].b;
        dfs(vv,y+v[x]);
        minn[x]=min(minn[x],minn[vv]);
        maxn[x]=max(maxn[x],maxn[vv]);
        u=a[u].a;
      }
    }
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout); 
      read(n); read(k);
      rep(i,1,n) read(v[i]);
      rep(i,1,n) minn[i]=INF;
      rep(i,1,n-1)
      {
        ll x,y;
        read(x); read(y); arr(x,y); fa[y]=x;
      }
      dfs1(1);
      build(1,1,n); cnt=0;
      dfs(1,0);
      rep(i,1,k)
      {
        ll x=data1[1],y=data2[1],z=data3[1];
        ans+=z;
        int kk1=minn[x]-1,kk2=minn[x]; 
        while (x!=y)
        {
          if (kk1>=minn[x]) change(1,1,n,minn[x],kk1,x,-(sum[x]-sum[y]));
          if (kk2<=maxn[x]) change(1,1,n,kk2,maxn[x],x,-(sum[x]-sum[y]));
          kk1=minn[x]-1; kk2=maxn[x]+1;
          x=fa[x];
        }
      }
      cout<<ans<<endl;
      return 0;
    }
  • 相关阅读:
    训练计划
    LA_3942 LA_4670 从字典树到AC自动机
    HDU 6180 Schedule
    HDU 6153 KMP
    HDU 2087 HDU 1867 KMP标准模板题
    Struts2学习8--文件上传(单个文件上传)
    SSH错误之--Error getting property descriptor: null at com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor.getProperty
    Struts2学习7---集合类型的类型转换
    工具-windows命令--查看端口占用情况,关闭端口
    Struts2学习6—OGNL (1)
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9201741.html
Copyright © 2020-2023  润新知