zoukankan      html  css  js  c++  java
  • [湖南集训]谈笑风生

    谈笑风生

    题目大意:

    给定a,求任何一个距 a 距离不超过给定的 k 的 b ,然后求一个 c 使得其为 a,b 的后代,求这样的三元组共有多少个。

    数据结构好题啊!

    解法分析:

    我们可以深搜两遍(其实一遍也行),然后对于每个节点去权值线段树上跑一跑,记录 dfs 序,然后就成功地与江大大谈笑风生了。


    //by Judge
    #include<cstdio>
    #include<iostream>
    #define ll long long
    #define mid (l+r>>1)
    using namespace std;
    const int M=3e5+7;
    #ifndef Judge
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    #endif
    char buf[1<<21],*p1=buf,*p2=buf;
    inline int read(){ int x=0,f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
    } char sr[1<<21],z[20];int C=-1,Z;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    inline void print(ll x,char chr='
    '){
        if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]=chr;
    } int n,m,q,p,k,pat,tim,cnt,le,ri,head[M],rt[M];
    int dep[M],siz[M],dfn[M],L[M*21],R[M*21]; ll ans,sum[M*21];
    struct Edge{ int to,next; }e[M<<1];
    inline void add(int u,int v){
    	e[++pat]={v,head[u]},head[u]=pat;
    	e[++pat]={u,head[v]},head[v]=pat;
    } void update(int las,int& now,int l,int r,int pos,int v){
    	if(!now) now=++cnt; sum[now]=sum[las]+v; if(l==r) return ;
    	if(pos<=mid) R[now]=R[las],update(L[las],L[now],l,mid,pos,v);
    	else L[now]=L[las],update(R[las],R[now],mid+1,r,pos,v);
    } ll query(int u,int v,int l,int r,int ql,int qr){
    	if(l>qr||ql>r) return 0; if(ql<=l&&r<=qr) return sum[v]-sum[u];
    	return query(L[u],L[v],l,mid,ql,qr)+query(R[u],R[v],mid+1,r,ql,qr);
    } inline void cmax(int& a,int b){ if(a<b) a=b; }
    #define v e[i].to
    void prep(int u,int fa){
    	siz[u]=1,dep[u]=dep[fa]+1,cmax(m,dep[u]);
    	for(int i=head[u];i;i=e[i].next)
    		if(v^fa) prep(v,u),siz[u]+=siz[v];
    } void dfs(int u,int fa){ dfn[u]=++tim;
    	update(rt[tim-1],rt[tim],1,m,dep[u],siz[u]-1);
    	for(int i=head[u];i;i=e[i].next) if(v^fa) dfs(v,u);
    }
    int main(){ n=read(),q=read();
    	for(int i=1,x,y;i<n;++i)
    		x=read(),y=read(),add(x,y);
    	for(prep(1,0),dfs(1,0);q;--q){
    		p=read(),k=read(),le=dfn[p],ri=le+siz[p]-1;
    		ans=query(rt[le],rt[ri],1,m,dep[p]+1,dep[p]+k);
    		ans+=1ll*min(dep[p]-1,k)*(siz[p]-1),print(ans);
    	} return Ot(),0;
    }
    
  • 相关阅读:
    bzoj 3238
    bzoj 3473 后缀自动机多字符串的子串处理方法
    bzoj 2998 第k小字串
    bzoj 3672 利用点分治将CDQ分治推广到树型结构上
    bzoj 3671 贪心
    NOIP模拟题——nan
    NOIP模拟题——kun(栈)
    hduP2586——How far away ?
    DP习题
    NOIP模拟题——来自风平浪静的明天
  • 原文地址:https://www.cnblogs.com/Judge/p/9963551.html
Copyright © 2011-2022 走看看