zoukankan      html  css  js  c++  java
  • [BZOJ3653]谈笑风生 主席树

    题面

    这道题应该比较裸吧。

    (a),(b)都是(c)的祖先。

    那么第一种情况是(b)(a)的祖先,那么方案数就是(min{dep[a]-1,k}cdot (num[a]-1))

    第二种是(a)(b)的祖先,那么方案数是

    [sum_{cin subtree(a),dep[c]-dep[a]leq k} num[c]-1 ]

    显然这东西用主席树,一个维度是dfs序,一个维度数深度维护一下就好了吧。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define REP(i,a,n) for(register int i(a);i<=(n);++i)
    #define FEC(i,x,y) for(register int i=head[x],y=g[i].to;i;i=g[i].ne,y=g[i].to)
    #define dbg(...) fprintf(stderr,__VA_ARGS__)
    const int SZ=(1<<21)+1;char ibuf[SZ],*iS,*iT,obuf[SZ+128],*oS=obuf,*oT=obuf+SZ-1;
    #ifdef ONLINE_JUDGE
    #define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SZ,stdin),(iS==iT?EOF:*iS++)):*iS++)
    #else
    #define gc() getchar()
    #endif
    template<typename I>inline void read(I&x){char c=gc();int f=0;for(;c<'0'||c>'9';c=gc())c=='-'?f=1:0;for(x=0;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+(c&15);f?x=-x:0;}
    inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
    #define printf(...) (oS>oT&&(flush(),1),oS+=sprintf(oS,__VA_ARGS__))
    template<typename A,typename B>inline char SMAX(A&a,const B&b){return a<b?a=b,1:0;}
    template<typename A,typename B>inline char SMIN(A&a,const B&b){return a>b?a=b,1:0;}
    typedef long long ll;typedef unsigned long long ull;typedef std::pair<int,int>pii;
    
    const int N=300000+7;
    int n,Q,x,y,dfn[N],pre[N],dfc,dep[N],num[N],a[N],T;
    struct Edge{int to,ne;}g[N<<1];int head[N],tot;
    inline void Addedge(int x,int y){g[++tot].to=y;g[tot].ne=head[x];head[x]=tot;}
    
    inline void DFS(int x,int fa=0){
    	dfn[x]=++dfc;pre[dfc]=x;dep[x]=dep[fa]+1;num[x]=1;
    	FEC(i,x,y)if(y!=fa)DFS(y,x),num[x]+=num[y];
    }
    
    struct Node{int lc,rc,id;ll val;}t[N*21];int RT[N],nod;
    inline void Insert(int&o,int L,int R,int x,int k){
    	if(t[o].id!=T)t[++nod]=t[o],t[o=nod].id=T;t[o].val+=k;if(L==R)return;
    	int M=(L+R)>>1;x<=M?Insert(t[o].lc,L,M,x,k):Insert(t[o].rc,M+1,R,x,k);
    }
    inline ll Query(int o,int p,int L,int R,int l,int r){
    	if(l<=L&&R<=r)return t[o].val-t[p].val;
    	int M=(L+R)>>1;if(r<=M)return Query(t[o].lc,t[p].lc,L,M,l,r);if(l>M)return Query(t[o].rc,t[p].rc,M+1,R,l,r);
    	return Query(t[o].lc,t[p].lc,L,M,l,r)+Query(t[o].rc,t[p].rc,M+1,R,l,r);
    }
    
    inline char cmp(const int&x,const int&y){return dep[x]<dep[y];}
    int main(){
    	read(n);read(Q);REP(i,1,n-1)read(x),read(y),Addedge(x,y),Addedge(y,x);
    	DFS(1);REP(i,1,n)a[i]=i;std::sort(a+1,a+n+1,cmp);int p=1;
    	REP(i,1,n){
    		++T;RT[i]=RT[i-1];
    		while(p<=n&&dep[a[p]]==i)Insert(RT[i],1,n,dfn[a[p]],num[a[p]]-1),++p;//错误笔记:这里的i,p要分清楚不能弄混掉了
    	}
    	REP(i,1,Q){
    		read(x),read(y);//错误笔记:同第49行,i,x要分清楚 
    		printf("%lld
    ",std::min(dep[x]-1,y)*(ll)(num[x]-1)+Query(RT[std::min(dep[x]+y,n)],RT[dep[x]],1,n,dfn[x],dfn[x]+num[x]-1));//错误笔记:要把dep[x]+y和n取个min,不然的话还没更新过
    	}return flush(),0;
    }
    
  • 相关阅读:
    分页
    用于dbnull的数据转换。因为用convert.to无法转换dbnull类型
    sqldbhelper
    sql 去重
    wcf 双工
    WCF使用泛型方法的问题
    wpf 查找页面的所有TextBox
    WebService流行框架之Axis和CXF
    Hibernate SQL方言 (hibernate.dialect)
    Hibernate联合主键映射
  • 原文地址:https://www.cnblogs.com/hankeke/p/BZOJ3653.html
Copyright © 2011-2022 走看看