[机房测试]不正常序列

我们定义一个不正常数列
F[1]=1
F[i]=(a*M+b*i+c) mod (1e9+7)
其中,M是指数列 { F[i] } 的中位数
如果数列一共有偶数项,那么我们定义较小的那个为他的中位数
对于给定的a,b,c和n,求数列F[i]之和

一句话题意:实时更新数列并查询数列中位数

很显然,我们可以用两个堆,储存这个数列的前半部分和后半部分
这两个堆的堆顶就是中位数了(具体是哪个堆的堆顶要分情况)
但这样时间复杂度不优秀,优化的方法如下:
在两个堆之间连一个数组,作为“缓冲区”
那么每次加入新数的时候,有可能只是数字在缓冲区上移动
并不涉及堆的操作,就可以优化时间复杂度

堆可以使用优先队列实现

代码:

#include<bits/stdc++.h>
#define mod 1000000007
#define size1 q1.size()
#define size2 q2.size()
#define ll long long
using namespace std;

ll a,b,c,n,mid,ans;
ll f[2000005];
priority_queue<ll> q1;//前面一半的数 
priority_queue<ll,vector<ll>,greater<ll> > q2;//后面一半的数 

template<class T>inline void read(T &res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

void insert(ll x)
{
    x<=q1.top() ? q1.push(x) : q2.push(x);
    if(size1>size2&&size1-size2>1)
    {
        q2.push(q1.top());
        q1.pop();
    }
    else if(size1<size2)
    {
        q1.push(q2.top());
        q2.pop();
    }
    return;
}

int main()
{
    freopen("unnormal.in","r",stdin);
    freopen("unnormal.out","w",stdout);
    read(a);read(b);read(c);read(n);
    f[1]=1; q1.push(1);
    for(register int i=2;i<=n;++i)
    {
        mid=q1.top();
        f[i]=(a*mid+b*i+c)%mod;
        insert(f[i]);
    }
    for(register int i=1;i<=n;++i) ans+=f[i];
    printf("%lld\n",ans);
    return 0;
}

考试的时候WA了7个点,因为答案 \(ans\) 并没有要求取模
毒瘤出题人。。。

猜你喜欢

转载自www.cnblogs.com/tqr06/p/11586994.html