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

    Problem

    ( ext{Solution:})

    题意很清楚:维护有序三元组 ((a,b,c),a,k) 已知,使得 (a,bin ancestor_c, ext{dis(a,b)}leq k.)

    观察到 (c) 的祖先一定在一条链上。分类讨论一下:

    • (dep_b<dep_c) 则与它们配对的 (c) 的数目等于 (siz[a]-1.)

    • (dep_b>dep_c) 则与它们配对的 (c) 的数目等于 (sum siz[b]-1.)

    于是考虑维护这两个东西。由于 (a,k) 已知,那么我们就可以将第二种情况转化成:维护深度区间在 ([dep_a+1,dep_a+k]) 的节点 (siz) 和。

    那这东西就很显然可以用线段树合并来维护了:每一个点建立以深度为序的线段树,单点修改,区间查询。

    时间复杂度 (O(nlog n).) 空间复杂度也是 (O(nlog n).) 注意答案会爆 ( ext{int}).

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N=6e5+10;
    const int MAXN=8e6+10;
    int Maxdep,node;
    vector<int>vec[N],pos[N];
    long long ans[N];
    inline int read() {
    	int s=0;
    	char ch=getchar();
    	while(!isdigit(ch))ch=getchar();
    	while(isdigit(ch)) {
    		s=s*10-48+ch;
    		ch=getchar();
    	}
    	return s;
    }
    inline int Max(int x,int y){return x>y?x:y;}
    inline int Min(int x,int y){return x<y?x:y;}
    int sum[MAXN],ls[MAXN],rs[MAXN],rub[MAXN<<1],ttop;
    int siz[MAXN],dep[MAXN],pa[MAXN],head[MAXN],tot;
    int rt[MAXN],n,q;
    struct E {
    	int nxt,to;
    } e[N<<1];
    inline void add(int x,int y) {
    	e[++tot]=(E) {
    		head[x],y
    	};
    	head[x]=tot;
    }
    inline int bd(){
    	if(ttop)return rub[ttop--];
    	return ++node;
    }
    void del(int x){
    	ls[x]=sum[x]=rs[x]=0;
    	rub[++ttop]=x;
    }
    inline void pushup(int x){sum[x]=sum[ls[x]]+sum[rs[x]];}
    int merge(int x,int y,int l,int r){
    	if(!x||!y)return x+y;
    	if(l==r){
    		sum[x]+=sum[y];
    		del(y);
    		return x;
    	}
    	int mid=(l+r)>>1;
    	ls[x]=merge(ls[x],ls[y],l,mid);
    	rs[x]=merge(rs[x],rs[y],mid+1,r);
    	pushup(x);return x;
    }
    void dfs(int x,int fa){
    	pa[x]=fa;
    	dep[x]=dep[fa]+1;
    	Maxdep=Max(Maxdep,dep[x]);
    	siz[x]=1;
    	for(int i=head[x];i;i=e[i].nxt){
    		int j=e[i].to;
    		if(j==fa)continue;
    		dfs(j,x);siz[x]+=siz[j];
    	}
    }
    void change(int &x,int L,int R,int pos,int v){
    	if(!x)x=++node;
    	if(L==R){
    		sum[x]+=v;
    		return;
    	}
    	int mid=(L+R)>>1;
    	if(pos<=mid)change(ls[x],L,mid,pos,v);
    	else change(rs[x],mid+1,R,pos,v);
    	pushup(x);
    }
    int query(int x,int L,int R,int l,int r){
    	if(L>=l&&R<=r)return sum[x];
    	int mid=(L+R)>>1,res=0;
    	if(l<=mid)res=query(ls[x],L,mid,l,r);
    	if(mid<r)res+=query(rs[x],mid+1,R,l,r);
    	return res;
    }
    void dfs_merge(int x){
    	change(rt[x],1,Maxdep,dep[x],siz[x]-1);
    	for(int i=head[x];i;i=e[i].nxt){
    		int j=e[i].to;
    		if(j==pa[x])continue;
    		dfs_merge(j);
    		rt[x]=merge(rt[x],rt[j],1,Maxdep);
    	}
    	for(int i=0;i<(int)vec[x].size();++i){
    		int L=dep[x]+1,R=dep[x]+vec[x][i];
    //		cout<<x<<":["<<L<<" "<<R<<"]"<<endl;
    		ans[pos[x][i]]=1ll*query(rt[x],1,Maxdep,L,R);
    		ans[pos[x][i]]+=1ll*Min(dep[x]-1,vec[x][i])*(siz[x]-1);
    //		printf("ans:%d
    ",ans[pos[x][i]]);
    	}
    }
    void Debug(){
    	for(int i=1;i<=n;++i)printf("%lld:siz:%lld dep:%lld pa:%lld
    ",i,siz[i],dep[i],pa[i]);
    }
    signed main(){
    	n=read();q=read();
    	for(int i=1;i<n;++i){
    		int x=read(),y=read();
    		add(x,y);add(y,x);
    	}
    	dfs(1,0);
    //	Debug();
    	for(int i=1;i<=q;++i){
    		int p=read(),k=read();
    		vec[p].push_back(k);
    		pos[p].push_back(i);
    	}
    	dfs_merge(1);
    	for(int i=1;i<=q;++i)printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    动态传参
    函数的介绍
    文件的操作
    send email with formatted table
    minimize and close window with customed winform
    python algorithm
    something important about docker
    book list
    which language is suitable for what to do
    Find Duplicate Items in list fast
  • 原文地址:https://www.cnblogs.com/h-lka/p/14957375.html
Copyright © 2011-2022 走看看