51nod1680:区间求和(BIT & dp)

有n个数,给定一个k,求所有长度大于等于k的区间中前k大数的总和。这样就比较简单相信大家都会,所以此题要求当k=1~n的总和,即求

  nk=1nk+1i=1nj=i+k1  区间前K大和
Input
输入五个数n,a1,A,B,C。a1表示第一个数,A,B,C用来生成其余n-1个数。a(i)=(a(i-1)*A+B)mod C。1<=n<=1,000,000,0<=a1,A,B,C<=1,000,000,000
Output
一个数表示答案,最后答案对1,000,000,007取模。
Input示例
3 3 1 1 10
Output示例
63
样例解释:
三个数为3,4,5
K=1:[1,1]=3,[1,2]=[2,2]=4,[1,3]=[2,3]=[3,3]=5(表示各个区间在k=1时的答案)
K=2:[1,2]=7,[2,3]=[1,3]=9
K=3:[1,3]=12
题意: 求出所有区间前1大,前2大,前3大...前n大的数的和,当然前提是某个区间有足够的数。
思路:考虑[l,r]区间的前1大~前r-l+1大的数之和为ans1,转移到区间[l,r+1],
它的ans2就是ans2=ans1+(x+1)*a[r+1]+y,
其中x是[l,r]小于等于a[r+1]的数量,y是[l,r]大于a[r+1]的数的和,画图模拟下就知道了。
令dp[i]为所有右界为i的区间的ans,那么对于[1,i-1]中小于等于a[i]的数a[j],显然贡献了j次;
对于[1,i-1]中大于a[i]的数a[k],贡献了a[k]*k次,最后加上a[i]自己贡献了一次。
这些值离散化后用BIT维护即可。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e6+3;
const LL mod = 1e9+7;
LL a[maxn+3], b[maxn+3], s[2][maxn+3], dp[maxn];
void update(int pos, LL val, int id)
{
    for(int i=pos; i<=maxn; i+=i&-i)
    {
        s[id][i] += val;
        if(s[id][i] >= mod) s[id][i] -= mod;
    }
}
LL cal(int pos, int id)
{
    LL res = 0;
    for(int i=pos; i; i-=i&-i)
    {
        res += s[id][i];
        if(res >= mod) res -= mod;
    }
    return res;
}
int main()
{
    int n;
    LL x, y, z;
    scanf("%d%lld%lld%lld%lld",&n,&a[1],&x,&y,&z);
    b[1] = a[1];
    for(int i=2; i<=n; ++i)
        b[i] = a[i] = (a[i-1]*x+y)%z;
    sort(b+1, b+1+n);
    LL ans = 0;
    for(int i=1; i<=n; ++i)
    {
        int p = lower_bound(b+1,b+1+n,a[i])-b;
        LL small = cal(p, 0), big = (cal(maxn, 1)-cal(p, 1)+mod)%mod;
        dp[i] = (small+i)%mod*a[i]%mod + big;
        dp[i] = (dp[i] + dp[i-1])%mod;
        update(p, i, 0);
        update(p, a[i]*i%mod, 1);
    }
    for(int i=1; i<=n; ++i)
    {
        ans += dp[i];
        if(ans >= mod) ans -= mod;
    }
    printf("%lld\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值