zoukankan      html  css  js  c++  java
  • [Usaco2017 Jan]Promotion Counting 线段树合并模板/dfs序

    两种做法,因为是求整个子树的值域问题所以可以按dfs序把进点和出点的数量作差

    #include<bits/stdc++.h>  
    //#pragma comment(linker, "/STACK:1024000000,1024000000")   
    #include<stdio.h>  
    #include<algorithm>  
    #include<queue>  
    #include<string.h>  
    #include<iostream>  
    #include<math.h>                    
    #include<stack>
    #include<set>  
    #include<map>  
    #include<vector>  
    #include<iomanip> 
    #include<bitset>
    using namespace std;         //
     
    #define ll long long  
    #define ull unsigned long long
    #define pb push_back  
    #define FOR(a) for(int i=1;i<=a;i++) 
    #define sqr(a) (a)*(a)
    #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
    ll qp(ll a,ll b,ll mod){
        ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t;
    }
    struct DOT{ll x;ll y;};
    inline void read(int &x){int k=0;char f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())k=k*10+c-'0';x=k*f;} 
    const int dx[4]={0,0,-1,1};
    const int dy[4]={1,-1,0,0};
    const int inf=0x3f3f3f3f; 
    const ll Linf=0x3f3f3f3f3f3f3f3f;
    const ll mod=1e9+7;;
     
    const int maxn=1e5+34;
     
    int v[maxn];
     
     
    int nodecnt,root;
    int val[maxn],happen[maxn],l[maxn],r[maxn],rnd[maxn],size[maxn];
     
    void maintain(int x){size[x]=size[l[x]]+size[r[x]]+happen[x];}
    void rturn(int &k){int t=l[k];l[k]=r[t];r[t]=k;maintain(k);maintain(t);k=t;}
    void lturn(int &k){int t=r[k];r[k]=l[t];l[t]=k;maintain(k);maintain(t);k=t;}
    void insert1(int &x,int v){ //按大小
        if(!x){
            x=++nodecnt;
            l[x]=r[x]=0;
            val[x]=v;happen[x]=size[x]=1;rnd[x]=rand();return;
        }
        size[x]++;
        if(val[x]==v)happen[x]++;
        else if(v<val[x]){
            insert1(l[x],v);
            if(rnd[l[x]]<rnd[x])rturn(x);
        }else{
            insert1(r[x],v);
            if(rnd[r[x]]<rnd[x])lturn(x);
        }
    }
    void del(int &x,int v){
        if(!x)return;
        if(val[x]==v){
            if(happen[x]>1){happen[x]--;size[x]--;return;}
            if(!l[x]||!r[x])x=l[x]+r[x];
            else if(rnd[l[x]]<rnd[r[x]]){rturn(x);del(x,v);}
            else{lturn(x);del(x,v);}
        }else{
            size[x]--;
            if(v<val[x])del(l[x],v);
            else del(r[x],v);
        }
    }
    int rnk(int x,int v){
        if(!x)return 0;
        if(val[x]==v)return size[l[x]]+happen[x];
        else if(v<val[x])return rnk(l[x],v);
        else return size[l[x]]+happen[x]+rnk(r[x],v);
    }
    int kth(int x,int k){
        if(!x)return 0;
        if(k<=size[l[x]])return kth(l[x],k);
        else if(k>size[l[x]]+happen[x])
            return kth(r[x],k-size[l[x]]-happen[x]);
        else return val[x];
    }
    int ans;
    void pre(int x,int v){
        if(!x)return;
        if(v>val[x])ans=x,pre(r[x],v);
        else pre(l[x],v);
    }
    void suf(int x,int v){
        if(!x)return;
        if(v<val[x])ans=x,suf(l[x],v);
        else suf(r[x],v);
    }
     
    vector<int>G[maxn];
    int Ans[maxn];
     
    void dfs(int x){
        insert1(root,v[x]);
        int t1=nodecnt-rnk(root,v[x]);
        for(int i=0;i<G[x].size();i++){
            dfs(G[x][i]);
        }
        int t2=nodecnt-rnk(root,v[x]);
        Ans[x]=t2-t1;
     
    }
     
    int main(){
        int n;scanf("%d",&n);
        FOR(n)scanf("%d",&v[i]);
        for(int i=2,x;i<=n;i++){
            scanf("%d",&x);
            G[x].pb(i);
        }
        dfs(1);
        for(int i=1;i<=n;i++)printf("%d
    ",Ans[i]);
    }
    

    一开始没看到各点权不同把平衡树的求rank改了下

    -------------------------------------------------------------------------------------------------------------------------------------------------------

    另一种做法是每个点做一个权值线段树,然后把这些权值线段树合并起来

    由于线段树只要参数固定生成形状就固定,所以一开始是n个log长的链,每个节点代表一个区间,节点权是出现次数

    合并的时候因为大家结构一样所以就左边+左边,右边+右边

    空间时间都是nlogn

    #include<bits/stdc++.h>  
    //#pragma comment(linker, "/STACK:1024000000,1024000000")   
    #include<stdio.h>  
    #include<algorithm>  
    #include<queue>  
    #include<string.h>  
    #include<iostream>  
    #include<math.h>                    
    #include<stack>
    #include<set>  
    #include<map>  
    #include<vector>  
    #include<iomanip> 
    #include<bitset>
    using namespace std;         //
    
    #define ll long long  
    #define ull unsigned long long
    #define pb push_back  
    #define FOR(a) for(int i=1;i<=a;i++) 
    #define sqr(a) (a)*(a)
    #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
    ll qp(ll a,ll b,ll mod){
    	ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t;
    }
    struct DOT{ll x;ll y;};
    inline void read(int &x){int k=0;char f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())k=k*10+c-'0';x=k*f;} 
    const int dx[4]={0,0,-1,1};
    const int dy[4]={1,-1,0,0};
    const int inf=0x3f3f3f3f; 
    const ll Linf=0x3f3f3f3f3f3f3f3f;
    const ll mod=1e9+7;;
    
    const int maxn=2e6+34;
    
    int n,a[maxn],b[maxn];
    vector<int>G[maxn];
    
    int seg;
    int tree[maxn],lson[maxn],rson[maxn];
    
    int root[maxn],ans[maxn];
    
    void pushup(int rt){tree[rt]=tree[lson[rt]]+tree[rson[rt]];}
    void build(int &rt,int l,int r,int pos){
    	rt=++seg;
    	if(l==r){
    		tree[rt]=1;return;
    	}
    	int m=l+r>>1;
    	if(pos<=m)build(lson[rt],l,m,pos);
    	else build(rson[rt],m+1,r,pos);
    	pushup(rt);
    }
    int query(int rt,int l,int r,int a,int b){
    	if(a<=l&&b>=r)return tree[rt];
    	int m=l+r>>1;
    	int ret=0;
    	if(a<=m)ret+=query(lson[rt],l,m,a,b);
    	if(b>m)ret+=query(rson[rt],m+1,r,a,b);
    	return ret;
    }
    int merge(int x,int y){
    	if(!x)return y;if(!y)return x;
    	lson[x]=merge(lson[x],lson[y]);
    	rson[x]=merge(rson[x],rson[y]);
    	pushup(x);
    	return x;
    }
    
    void dfs(int u){
    	for(int i=0;i<G[u].size();i++){
    		int v=G[u][i];
    		dfs(v);
    		root[u]=merge(root[u],root[v]);
    	}
    	ans[u]=query(root[u],1,n,a[u]+1,n);
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		b[i]=a[i];
    	}
    	sort(b+1,b+1+n);
    	int tot=unique(b+1,b+1+n)-b-1;
    
    	for(int i=1;i<=n;i++){
    		a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
    	}
    	for(int i=2;i<=n;i++){
    		int x;scanf("%d",&x);
    		G[x].pb(i);
    	}
    	for(int i=1;i<=n;i++){
    		build(root[i],1,n,a[i]);
    	}
    	dfs(1);
    	for(int i=1;i<=n;i++){
    		printf("%d
    ",ans[i]);
    	}
    }

  • 相关阅读:
    TUN/TAP区别
    从日志文件解决ArcGIS Server性能低下问题的步骤(1)
    java异常
    Maven
    前车之鉴-web篇
    图论复习总结
    奇(qi)谋(ji)巧(yin)计(qiao)
    莫比乌斯反演呓语
    学习后缀数组笔记
    浅读叶青学长竞赛学习知识目录
  • 原文地址:https://www.cnblogs.com/Drenight/p/8611192.html
Copyright © 2011-2022 走看看