zoukankan      html  css  js  c++  java
  • 2019icpc南京网络赛 F 主席树

    题意

    给一个(n)的全排列数组(a),求一个递推数组每一项的值:(ans[i]=ans[j]+1)(j)(a[pos[i]-k]到a[pos[i]+k],(pos[i]为i在数组a中的下标))中小于(i)的最大的值。

    分析

    这题set的做法更优秀,但是想练习一下在主席树上二分。

    按权值建主席树,对每个(i)去查询(a[pos[i]-k]到a[pos[i]+k])中小于(i)的最大值,查询时先查询右儿子,再查询左儿子,因为找到的右儿子一定比左儿子大,直到找到一个满足条件的点。

    Code

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define ll long long
    using namespace std;
    const int inf=1e9;
    const int mod=1e9+7;
    const int maxn=1e5+10;
    int T;
    int n,k;
    int a[maxn],b[maxn],ans[maxn],tr[maxn*30],ls[maxn*30],rs[maxn*30],rt[maxn],tot;
    void bd(int l,int r,int &p){
    	tr[++tot]=tr[p],ls[tot]=ls[p],rs[tot]=rs[p],p=tot;
    	if(l==r) return;
    	int mid=l+r>>1;
    	bd(l,mid,ls[p]);bd(mid+1,r,rs[p]);
    }
    void up(int k,int l,int r,int &p){
    	tr[++tot]=tr[p]+1,ls[tot]=ls[p],rs[tot]=rs[p],p=tot;
    	if(l==r) return;
    	int mid=l+r>>1;	
    	if(k<=mid) up(k,l,mid,ls[p]);
    	else up(k,mid+1,r,rs[p]);
    }
    int qy(int dl,int dr,int l,int r,int a,int b){
    	if(tr[b]-tr[a]==0) return 0;
    	if(l>=dl&&r<=dr){
    		if(l==r) return l;
    		int mid=l+r>>1,res=0;
    		if(dr>mid) res=qy(dl,dr,mid+1,r,rs[a],rs[b]);
    		if(dl<=mid&&res==0) res=qy(dl,dr,l,mid,ls[a],ls[b]);
    		return res;
    	}int mid=l+r>>1,res=0;
    	if(dr>mid) res=qy(dl,dr,mid+1,r,rs[a],rs[b]);
    	if(dl<=mid&&res==0) res=qy(dl,dr,l,mid,ls[a],ls[b]);
    	return res;
    }
    int main(){
    	//ios::sync_with_stdio(false);
    	//freopen("in","r",stdin);
    	scanf("%d",&T);
    	while(T--){
    		tot=0;
    		scanf("%d%d",&n,&k);
    		for(int i=1;i<=n;i++){
    			scanf("%d",&a[i]);
    			b[a[i]]=i;
    		}
    		bd(1,n,rt[0]);
    		for(int i=1;i<=n;i++){
    			rt[i]=rt[i-1];
    			up(a[i],1,n,rt[i]);
    		}ans[1]=1;
    		for(int i=2;i<=n;i++){
    			int l=max(0,b[i]-k-1),r=min(n,b[i]+k);
    			ans[i]=ans[qy(1,i-1,1,n,rt[l],rt[r])]+1;
    		}
    		for(int i=1;i<=n;i++){
    			printf("%d",ans[i]);
    			if(i==n) printf("
    ");
    			else printf(" ");
    			ans[i]=0;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    sql声明变量,及if -else语句、while语句的用法
    视图、事务
    索引
    相关子查询
    递归实现treeView下的省市联动
    创建sqlhelp类以封装对数据库的操作及对可空类型的操作
    ADO.Net操作数据库
    sql的case语句
    vue父组件异步数据子组件接收遇到的坑
    第一次用angularJS做后台管理点滴
  • 原文地址:https://www.cnblogs.com/xyq0220/p/11443966.html
Copyright © 2011-2022 走看看