• bzoj 3653 谈笑风生 —— 主席树


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3653

    对于一个 (a,b,c),分成 b 是 a 的祖先和 b 在 a 子树里两部分;

    第一部分 b 可以选 min(dep[a]-1,k) 个,c 可以选 siz[a]-1 个,乘起来即可;

    第二部分,要求 ∑siz[u]-1,其中 u 是 a 子树内到 a 距离不超过 k 的点;

    考虑到子树在 dfs 序上就是一段区间,距离范围又可以看作 dep 范围,所以在 dfs 序上建主席树,就可以查询对应 dep 的和;

    别忘了 long long。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define mid ((l+r)>>1)
    using namespace std;
    typedef long long ll;
    int const xn=3e5+5,xm=xn*20;
    int n,hd[xn],ct,to[xn<<1],nxt[xn<<1],tim,dfn[xn],siz[xn],id[xn],dep[xn];
    int cnt,ls[xm],rs[xm],rt[xn];
    ll sum[xm];
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    int gt[20];
    void wr(ll x)
    {
      if(!x){putchar('0'); return;}
      if(x<0){putchar('-'); x=-x;}
      int t=0;
      while(x)gt[++t]=x%10,x/=10;
      for(int i=t;i;i--)putchar(gt[i]+'0');
    }
    void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
    void dfs(int x,int fa)
    {
      dfn[x]=++tim; id[tim]=x; siz[x]=1; dep[x]=dep[fa]+1;
      for(int i=hd[x],u;i;i=nxt[i])
        {
          if((u=to[i])==fa)continue;
          dfs(u,x); siz[x]+=siz[u];
        }
    }
    void update(int &x,int y,int l,int r,int pos,int v)
    {
      x=++cnt; ls[x]=ls[y]; rs[x]=rs[y]; sum[x]=sum[y]+v;
      if(l==r)return;
      if(pos<=mid)update(ls[x],ls[y],l,mid,pos,v);
      else update(rs[x],rs[y],mid+1,r,pos,v);
      sum[x]=sum[ls[x]]+sum[rs[x]];
    }
    ll query(int x,int y,int l,int r,int L,int R)
    {
      if(l>=L&&r<=R)return sum[y]-sum[x];
      ll ret=0;
      if(mid>=L)ret+=query(ls[x],ls[y],l,mid,L,R);
      if(mid<R)ret+=query(rs[x],rs[y],mid+1,r,L,R);
      return ret;
    }
    int main()
    {
      n=rd(); int q=rd();
      for(int i=1,x,y;i<n;i++)
        {
          x=rd(); y=rd();
          add(x,y); add(y,x);
        }
      dfs(1,0);
      for(int i=1;i<=n;i++)
        update(rt[i],rt[i-1],1,n,dep[id[i]],siz[id[i]]-1);
      for(int i=1,p,k;i<=q;i++)
        {
          p=rd(); k=rd();
          ll ans=(ll)min(dep[p]-1,k)*(siz[p]-1);
          ans+=query(rt[dfn[p]],rt[dfn[p]+siz[p]-1],1,n,dep[p]+1,dep[p]+k);
          wr(ans); puts("");
        }
      return 0;
    }
  • 相关阅读:
    workflow里xaml格式(备忘)
    Excel 读取
    自定义工作流活动的外观的两种方式(补充)
    用SQLite,Enterprise的报错
    WF 4.0
    升级 90天 vs2008 在win2008下。
    NUnitLite web下的用法
    screen常用方法 Lei
    中文摘要的写法 Lei
    bootstrap, boosting, bagging 几种方法的联系 Lei
  • 原文地址:https://www.cnblogs.com/Zinn/p/9868577.html
Copyright © 2020-2023  润新知