E1. Median on Segments(找一个数在多少个连续子序列中是中位数)

题目传送门

题意: 给你n(n<=1e5)个互不相同的数,给你一个数m,问你m在多少个连续子序列中是中位数,对于序列长度为偶数的情况,中位数取左边那个。

思路: 先找到m在序列中的位置,然后从这个位置开始向左跑到1(先向右跑到n也可以。),如果a[i]>m,就cnt++,a[i]<m则cnt–,用个map记录,每次ma[cnt]++。所以cnt表示的是大于m的数的个数和小于m的数的个数的差值,跑完这边之后,把cnt置为0,然后扫另一边,开始统计答案,统计的是ma[-cnt]和ma[-cnt+1]。

#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vi vector<int>
#define mii map<int,int>
#define pii pair<int,int>
#define ull unsigned long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;}
using namespace std;
const int N=2e5+5;
const int inf=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-6;
int a[N];
signed main()
{
    int n,m;
    cin>>n>>m;
    map<int,int>ma;int pos;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(a[i]==m)
            pos=i;
    }
    int cnt=0;
    for(int i=pos;i>=1;i--)
    {
        if(a[i]>m)
            cnt++;
        else if(a[i]<m)
            cnt--;
        ma[cnt]++;
    }
    cnt=0;
    int res=0;
    for(int i=pos;i<=n;i++)
    {
        if(a[i]>m)
            cnt++;
        else if(a[i]<m)
            cnt--;
        res+=ma[-cnt];
        res+=ma[-cnt+1];
    }
    cout<<res<<endl;
}

原创文章 144 获赞 13 访问量 8688

猜你喜欢

转载自blog.csdn.net/Joker_He/article/details/105798139