F. Scalar Queries 题解(思维+线段树)

题目链接

题目思路

考虑(a[i])的贡献

只有比(a[i])小的数才对(a[i])有贡献

假设有一个数(a[j]<a[i]&& j<i)

那么在区间([l,r] ;lleq j,ileq r)的情况下(a[i])至少要乘以2

(a[j])在右边同理

每次线段树先搞小的数,再搞大的数,然后再维护下

有点绕

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=5e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int n;
int a[maxn];
ll ans;
pair<int,int> pa[maxn];
ll tree[maxn<<2][2];
void update(int node ,int l,int r,int pos,int add,int op){
    if(l==r){
        tree[node][op]+=add;
        tree[node][op]%=mod;
        return ;
    }
    int mid=(l+r)/2;
    if(mid>=pos) update(node<<1,l,mid,pos,add,op);
    if(mid<pos)  update(node<<1|1,mid+1,r,pos,add,op);
    tree[node][op]=(tree[node<<1][op]+tree[node<<1|1][op])%mod;
}
int query(int node,int L,int R,int l,int r,int op){
    if(L>R) return 0;
    if(L<=l&&r<=R){
        return tree[node][op];
    }
    int mid=(l+r)/2;
    ll sum=0;
    if(mid>=L) sum+=query(node<<1,L,R,l,mid,op);
    if(mid<R)  sum+=query(node<<1|1,L,R,mid+1,r,op);
    sum%=mod;
    return sum;
}
signed main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        pa[i]={a[i],i};
    }
    sort(pa+1,pa+1+n);
    for(int i=1;i<=n;i++){
        int pos=pa[i].se;
        update(1,1,n,pos,pos,1);
        update(1,1,n,pos,n-pos+1,2);
        ll tmp=1ll*query(1,1,pos,1,n,1)*(n-pos+1)+1ll*query(1,pos+1,n,1,n,2)*pos;
        tmp%=mod;
        tmp=tmp*pa[i].fi%mod;
        ans=(ans+tmp)%mod;
    }
    printf("%lld
",ans);
    return 0;
}

不摆烂了,写题
原文地址:https://www.cnblogs.com/hunxuewangzi/p/15496831.html