zoukankan      html  css  js  c++  java
  • [bzoj3653]谈笑风生

    发现ac的祖先,bc的祖先,则ab也一定是祖先关系。

    a已经确定了,考虑b1.ab的祖先,考虑a中每一个节点作为c的方案数,显然就是min(d[x]-d[a]-1,k),其中x!=a且在a的子树中;2.ba的祖先,很好处理,即min(d[a],k)*(sz[a]-1)(深度从0开始)。

    第一个式子可以转化为min(d[x],k+d[a]+1)-d[a]-1,然后对于dfs序,开一棵可持久化权值线段树(权值为深度),对于区间维护区间深度和和区间个数,然后询问分两部分计算即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 300005
     4 #define ll long long
     5 #define mid (l+r>>1)
     6 struct ji{
     7     int nex,to;
     8 }edge[N<<1];
     9 int V,E,n,m,x,y,head[N],r[N],sh[N],sz[N],id[N],ls[N*30],rs[N*30];
    10 ll ans,f[N*20][2];
    11 void add(int x,int y){
    12     edge[E].nex=head[x];
    13     edge[E].to=y;
    14     head[x]=E++;
    15 }
    16 void update(int k1,int &k2,int l,int r,int x){
    17     k2=++V;
    18     f[k2][0]=f[k1][0]+1;
    19     f[k2][1]=f[k1][1]+x;
    20     if (l==r)return;
    21     ls[k2]=ls[k1];
    22     rs[k2]=rs[k1];
    23     if (x<=mid)update(ls[k1],ls[k2],l,mid,x);
    24     else update(rs[k1],rs[k2],mid+1,r,x);
    25 }
    26 ll query(int k1,int k2,int l,int r,int x,int y,int p){
    27     if ((l>y)||(x>r)||(!k2))return 0;
    28     if ((x<=l)&&(r<=y))return f[k2][p]-f[k1][p];
    29     return query(ls[k1],ls[k2],l,mid,x,y,p)+query(rs[k1],rs[k2],mid+1,r,x,y,p);
    30 }
    31 void dfs(int k,int fa,int s){
    32     id[k]=++x;
    33     if (x>1)update(r[x-1],r[x],1,n,s);
    34     sh[k]=s;
    35     sz[k]=1;
    36     for(int i=head[k];i!=-1;i=edge[i].nex)
    37         if (edge[i].to!=fa){
    38             dfs(edge[i].to,k,s+1);
    39             sz[k]+=sz[edge[i].to];
    40         }
    41 }
    42 int main(){
    43     V=r[1]=1;
    44     scanf("%d%d",&n,&m);
    45     memset(head,-1,sizeof(head));
    46     for(int i=1;i<n;i++){
    47         scanf("%d%d",&x,&y);
    48         add(x,y);
    49         add(y,x);
    50     }
    51     x=0;
    52     dfs(1,0,0);
    53     for(int i=1;i<=m;i++){
    54         scanf("%d%d",&x,&y);
    55         ans=1LL*(sz[x]-1)*min(-1,y-sh[x]-1);
    56         y+=sh[x]+1;
    57         ans+=query(r[id[x]],r[id[x]+sz[x]-1],1,n,1,min(n,y),1);
    58         if (y<n)ans+=query(r[id[x]],r[id[x]+sz[x]-1],1,n,y+1,n,0)*y;
    59         printf("%lld\n",ans);
    60     }
    61 }
    View Code
  • 相关阅读:
    【leetcode】Spiral Matrix
    【leetcode】Permutations
    【leetcode】Search Insert Position
    【leetcode】Search for a Range
    文件名对目标文件夹可能过长
    协同过滤和简单SVD优化
    奇异值分解(SVD)和简单图像压缩
    PCA数据降维
    FP-growth高效频繁项集发现
    关联挖掘和Aprioir算法
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249841.html
Copyright © 2011-2022 走看看