zoukankan      html  css  js  c++  java
  • [BZOJ]3653: 谈笑风生

    题解:

    答案贡献分为两部分 

    第一部分为  b是a的祖先是  $ ans=min(dep[p]-1,k)*(num[p]-1) $

    第二部分为  b是a的子孙节点  对于dfs建深度主席树  每个点的权值为子孙节点个数 然后查询对应dfs序区间 及相应的深度范围

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=3e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int n,m;
    int dep[MAXN],num[MAXN],fa[MAXN],p[MAXN],fp[MAXN],cnt;
    void dfs(int x,int pre,int deep){
        dep[x]=deep+1;num[x]=1;fa[x]=pre;p[x]=++cnt;fp[p[x]]=x;
        link(x)if(j->t!=pre)dfs(j->t,x,deep+1),num[x]+=num[j->t];
    }
    
    typedef struct node{
        int l,r;ll sum;
    }node;
    node d[MAXN*21];
    int cnt1,rt[MAXN];
    
    void update(int &x,int y,int l,int r,int t,int k){
        x=++cnt1;d[x]=d[y];d[x].sum+=k;
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(t<=mid)update(d[x].l,d[y].l,l,mid,t,k);
        else update(d[x].r,d[y].r,mid+1,r,t,k);
    }
    
    ll ans1;
    void query(int x,int y,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){ans1+=(d[y].sum-d[x].sum);return ;}
        int mid=(l+r)>>1;
        if(ql<=mid)query(d[x].l,d[y].l,l,mid,ql,qr);
        if(qr>mid)query(d[x].r,d[y].r,mid+1,r,ql,qr);
    }
    
    int main(){
        n=read();m=read();
        int u,v;
        inc(i,2,n)u=read(),v=read(),add(u,v),add(v,u);
        dfs(1,0,0);
        inc(i,1,cnt)update(rt[i],rt[i-1],1,n,dep[fp[i]],num[fp[i]]-1);
        while(m--){
    	u=read();v=read();
    	ll ans=1ll*min(dep[u]-1,v)*(num[u]-1);
    	ans1=0;query(rt[p[u]],rt[p[u]+num[u]-1],1,n,dep[u]+1,min(dep[u]+v,n));
    	printf("%lld
    ",ans1+ans);
        }
        return 0;
    }
    

      

    3653: 谈笑风生

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 1278  Solved: 549
    [Submit][Status][Discuss]

    Description

    设T 为一棵有根树,我们做如下的定义:
    ? 设a和b为T 中的两个不同节点。如果a是b的祖先,那么称“a比b不知道
    高明到哪里去了”。
    ? 设a 和 b 为 T 中的两个不同节点。如果 a 与 b 在树上的距离不超过某个给定
    常数x,那么称“a 与b 谈笑风生”。
    给定一棵n个节点的有根树T,节点的编号为1 到 n,根节点为1号节点。你需
    要回答q 个询问,询问给定两个整数p和k,问有多少个有序三元组(a;b;c)满足:
    1. a、b和 c为 T 中三个不同的点,且 a为p 号节点;
    2. a和b 都比 c不知道高明到哪里去了;
    3. a和b 谈笑风生。这里谈笑风生中的常数为给定的 k。

    Input

    第一行含有两个正整数n和q,分别代表有根树的点数与询问的个数。
    接下来n - 1行,每行描述一条树上的边。每行含有两个整数u和v,代表在节点u和v之间有一条边。
    接下来q行,每行描述一个操作。第i行含有两个整数,分别表示第i个询问的p和k。
    1<=P<=N
    1<=K<=N
    N<=300000
    Q<=300000
     

    Output

    输出 q 行,每行对应一个询问,代表询问的答案。

    Sample Input

    5 3
    1 2
    1 3
    2 4
    4 5
    2 2
    4 1
    2 3

    Sample Output

    3
    1
    3

    HINT

    Hint:边要加双向

        

  • 相关阅读:
    java的构造方法 java程序员
    No result defined for action cxd.action.QueryAction and result success java程序员
    大学毕业后拉开差距的真正原因 java程序员
    hibernate的回滚 java程序员
    验证码 getOutputStream() has already been called for this response异常的原因和解决方法 java程序员
    浅谈ssh(struts,spring,hibernate三大框架)整合的意义及其精髓 java程序员
    你平静的生活或许会在某个不可预见的时刻被彻底打碎 java程序员
    Spring配置文件中使用ref local与ref bean的区别. 在ApplicationResources.properties文件中,使用<ref bean>与<ref local>方法如下 java程序员
    poj1416Shredding Company
    poj1905Expanding Rods
  • 原文地址:https://www.cnblogs.com/wang9897/p/10363769.html
Copyright © 2011-2022 走看看