zoukankan      html  css  js  c++  java
  • 【题解】[USACO17JAN]Promotion Counting P

    Problem

    ( ext{Solution:})

    题目求的就是一棵子树中大于根节点权值的节点数。

    这东西一看就很权值线段树。

    然后发现这东西又很线段树合并。

    考虑对每一个点维护一棵权值线段树。这样,我们将子树的信息合并到根的权值树上,就可以做到 (nlog n) 合并信息了。

    然后对每个节点进行查询即可。权值树上维护一下区间和即可。由于空间问题要动态开点。

    线段树合并的空间复杂度是 (O(nlog n)) 的,又有一个约为 (2) 的常数(从某处看到的)(这是动态开点线段树合并的复杂度)

    所以开到 (3.2cdot 10^6) 就可以了。

    懒得思考怎么直接求,实际上可以用差分的思想,更新完一棵子树后,用更新前的信息减去更新后的信息即可。这样用树状数组也可以解决问题。

    就当练习一下线段树合并了。

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=3.2e6+10;
    const int N=2e5+10;
    int head[MAXN],tot,cnt,n,m;
    int ls[MAXN],rs[MAXN],ans[MAXN];
    int dep[MAXN],pa[MAXN],siz[MAXN];
    int b[MAXN],bcnt,blen;
    int v[MAXN],val[MAXN];
    struct E{int nxt,to;}e[MAXN];
    inline void add(int x,int y){e[++tot]=(E){head[x],y};head[x]=tot;}
    int rt[MAXN],sum[MAXN];
    inline int getpos(int v){return lower_bound(b+1,b+blen+1,v)-b;}
    void dfs(int x,int fa){
    	dep[x]=dep[fa]+1;
    	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];
    	}
    }
    inline void pushup(int x){sum[x]=sum[ls[x]]+sum[rs[x]];}
    int change(int x,int l,int r,int pos,int v){
    	if(!x)x=++cnt;
    	if(l==r){
    		sum[x]+=v;
    		return x;
    	}
    	int mid=(l+r)>>1;
    	if(pos<=mid)ls[x]=change(ls[x],l,mid,pos,v);
    	else rs[x]=change(rs[x],mid+1,r,pos,v);
    	pushup(x);return x;
    }
    int merge(int x,int y,int l,int r){
    	if(!x||!y)return x+y;
    	if(l==r){
    		sum[x]+=sum[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;
    }
    int query(int x,int l,int r,int ql,int qr){
    	if(l>=ql&&r<=qr)return sum[x];
    	int mid=(l+r)>>1,ans=0;
    	if(ql<=mid)ans+=query(ls[x],l,mid,ql,qr);
    	if(mid<qr)ans+=query(rs[x],mid+1,r,ql,qr);
    	return ans;
    }
    void DFS(int x){
    	for(int i=head[x];i;i=e[i].nxt){
    		int j=e[i].to;
    		if(j==pa[x])continue;
    		DFS(j);
    		rt[x]=merge(rt[x],rt[j],1,N);
    	}
    	ans[x]=query(rt[x],1,N,val[x]+1,N);
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)scanf("%d",&v[i]);
    	for(int i=1;i<=n;++i)b[++bcnt]=v[i];
    	sort(b+1,b+bcnt+1);
    	blen=unique(b+1,b+bcnt+1)-b-1;
    	for(int i=1;i<=n;++i){
    		int pos=getpos(v[i]);
    		val[i]=pos;
    	}
    	for(int i=1;i<=n;++i)rt[i]=change(rt[i],1,N,val[i],1);
    	for(int i=2;i<=n;++i){
    		int x;
    		scanf("%d",&x);
    		add(x,i);pa[i]=x;
    	}
    	dfs(1,0);
    	DFS(1);
    	for(int i=1;i<=n;++i)printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    WampServer Mysql配置
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 前10名
  • 原文地址:https://www.cnblogs.com/h-lka/p/14943417.html
Copyright © 2011-2022 走看看