zoukankan      html  css  js  c++  java
  • [Usaco2011]Above the Median

    知识点前置

    ·树状数组

    题面来源

    https://www.luogu.com.cn/problem/P3031

    题目大意

    给你一个长度为 (n) 序列,求出满足以下条件的子序列个数有多少个:
    中位数大于给出的 (k)

    解题方法

    自己想了半天才打出来
    --------------------分割线--------------------
    因为我们要求的区间中,每个数 (a_i)对于 (k)来说,只有两种情况:

    [a_i>=k||a_i<k ]

    那么,我们把(a_i>=k)这个位置打成1,而(a_i<k)打成-1,那么就变成了这样(k=6时):

    num 10 5 6 2
    a 1 -1 1 -1

    然后我们再把这个a丢到树状数组里去做前缀和,就得到了

    sum 1 0 1 0

    这个时候,我们就可以一遍一遍的查在(i)这个位置之前有多少个数字sum比sum[i]小,最后整合相加得到答案
    注意:前缀和sum可能为负数,所以在搜的时候,把每个位置保险起见加上一个n+1,不影响结果

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=200005;//maxn开两倍
    
    long long n,x,ans;
    long long a[maxn],num[maxn],sum[maxn];
    
    void add(int x,int vol)
    {
    	while(x<=n+n+1)
    	{
    		sum[x]+=vol;
    		x+=(x & -x);
    	}
    }
    
    int query(int x)
    {
    	int ret=0;
    	while(x)
    	{
    		ret+=sum[x];
    		x-=(x & -x);
    	}
    	return ret;
    }
    
    int main()	
    {
    	scanf("%lld%lld",&n,&x);
    	a[0]=0;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lld",&num[i]);
    		if(num[i]>=x)a[i]=a[i-1]+1;
    		else		 a[i]=a[i-1]-1;
    	}
    	add(n+1,1);//预处理0的位置
    	for(int i=1;i<=n;i++)
    	{
    		ans+=query(a[i]+n+1); 
    		add(a[i]+n+1,1);
    	}
    	printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    在IDEA上本地更新同步Git中的更改
    protobuf的序列化和反序列化
    关于Pytorch报警告:Warning: indexing with dtype torch.uint8 is now deprecated, please use a dtype torch.bool instead
    990. 等式方程的可满足性
    死锁
    事务隔离
    Lab-1
    软件测试homework3
    TCP/UDP网络连接的固定写法
    软件测试Homework 2
  • 原文地址:https://www.cnblogs.com/jyx-txzr/p/13234261.html
Copyright © 2011-2022 走看看