• csp-s模拟测试52平均数,序列题解


    题面:https://www.cnblogs.com/Juve/articles/11602244.html

    平均数:

    第k个平均数不好求,我们考虑二分,转化成平均数小于x的有几个

    虑把序列中的每个数减去 x,则我们只需求区间和小于 0 的区间数量。

    我们对这个序列求前缀和,则区间[L,R]和小于 0 当且仅当 SL-1>SR,

    答案即为前缀和序列 S 的逆序对数量,使用经典的归并排序即可解决

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define int long long
    #define double long double
    using namespace std;
    const int MAXN=1e5+5;
    int n,k,ans=0;
    double L=0.0,R=1e9+1,sum[MAXN],temp[MAXN],res,a[MAXN];
    double max(double a,double b){
    	return a>b?a:b;
    }
    void merge_sort(int l,int r){
    	int mid,i,j,k;
    	if(l==r) return;
    	mid=(l+r)/2;
    	merge_sort(l,mid);merge_sort(mid+1,r);
    	i=l;j=mid+1;k=l;
    	while(i<=mid&&j<=r){
    		if(sum[i]>sum[j]){
    			ans+=mid-i+1;
    			temp[k]=sum[j];
    			j++;   
    			k++; 
    		}else{  
    		    temp[k]=sum[i]; 
    			i++;
    			k++;
    		}
    	}
    	while(i<=mid){
    		temp[k]=sum[i];  
            i++;  
            k++;
    	}
    	while(j<=r){   
            temp[k]=sum[j];  
            j++;  
            k++; 
        }
        for(i=l;i<=r;i++)
        	sum[i]=temp[i];
    }
    bool check(double x){
    	ans=0;
    	sum[0]=0;
    	for(int i=1;i<=n;++i){
    		sum[i]=sum[i-1]+a[i]-x;
    	}
    	merge_sort(0,n);
    	return ans<k;
    }
    signed main(){
    	scanf("%lld%lld",&n,&k);
    	for(int i=1;i<=n;++i){
    		scanf("%Lf",&a[i]);
    	}
    	while(L<R-(1e-5)){
    		double mid=(L+R)/2.0;
    		if(check(mid)) L=mid;
    		else R=mid;
    	}
    	printf("%0.4Lf
    ",L);
    	return 0;
    }
    

    序列:

    考虑主席树,相当与对每一个位置建一棵动态开点权值线段树,

    我们不能把所有区间插进去,我们插入询问,对于每一个位置,经过它的询问有很多,我们统计a[i]对整个答案的贡献

    我们对每一个位置插入所有在这个位置上要查询的x,然后答案就是对于每一个位置i,在i所在的线段树中找小于a[i]的x的数量,这是a[i]对整个答案的贡献

    修改后我们还像之前那样查询,如果将p位置更改为v,那么减去a[p]的贡献,在加上更改后的v对整个答案的贡献

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define int long long
    #define re register
    using namespace std;
    const int MAXN=1e5+5;
    int n,m,q,a[MAXN],ans,x[MAXN];
    int root[MAXN],tot=0,ls[MAXN<<6],rs[MAXN<<6],tr[MAXN<<6];
    struct node{
    	int pos,val;
    };
    vector<node>v[MAXN];
    inline void insert(re int &k,re int pre,re int l,re int r,re int pos,re int val){
    	k=++tot;
    	ls[k]=ls[pre],rs[k]=rs[pre],tr[k]=tr[pre];
    	if(l==r){
    		tr[k]+=val;
    		return ;
    	}
    	re int mid=(l+r)>>1;
    	if(pos<=mid) insert(ls[k],ls[pre],l,mid,pos,val);
    	else insert(rs[k],rs[pre],mid+1,r,pos,val);
    	tr[k]=tr[ls[k]]+tr[rs[k]];
    }
    inline int query(re int k,re int l,re int r,re int opl,re int opr){
    	if(opl<=l&&r<=opr) return tr[k];
    	re int mid=(l+r)>>1,res=0;
    	if(opl<=mid) res+=query(ls[k],l,mid,opl,opr);
    	if(opr>mid) res+=query(rs[k],mid+1,r,opl,opr);
    	return res;
    }
    signed main(){
    	scanf("%lld%lld%lld",&n,&m,&q);
    	for(re int i=1;i<=n;++i){
    		scanf("%lld",&a[i]);
    	}
    	for(re int i=1,l,r;i<=m;++i){
    		scanf("%lld%lld%lld",&l,&r,&x[i]);
    		v[l].push_back((node){x[i],1});
    		v[r+1].push_back((node){x[i],-1});
    	}
    	for(re int i=1;i<=n;++i){
    		root[i]=root[i-1];
    		int N=v[i].size();
    		for(re int j=0;j<N;++j){
    			insert(root[i],root[i],1,n,v[i][j].pos,v[i][j].val);
    		}
    	}
    	for(re int i=1;i<=n;++i){
    		ans+=query(root[i],1,n,1,a[i]);
    	}
    	printf("%lld
    ",ans);
    	for(re int i=1,p,v;i<=q;++i){
    		scanf("%lld%lld",&p,&v);
    		p^=ans,v^=ans;
    		ans+=(query(root[p],1,n,1,v)-query(root[p],1,n,1,a[p]));
    		a[p]=v;
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    aspjpeg组件安装、使用常见问题
    调用过程sub时不能使用括号
    asp中,使用js打开别的网址注意点
    让文件夹属性出现“安全”选项卡
    C#正则表达式使用<转载备用>
    .NET编程中常用的路径表示方式<转>
    DIVWEB布局
    winform report<收藏>
    Delphi中MessageBox用法
    DW中常用标签
  • 原文地址:https://www.cnblogs.com/Juve/p/11602405.html
Copyright © 2020-2023  润新知