F. Scalar Queries 题解(思维+线段树)
题目链接
题目思路
考虑\(a[i]\)的贡献
只有比\(a[i]\)小的数才对\(a[i]\)有贡献
假设有一个数\(a[j]<a[i]\&\& j<i\)
那么在区间\([l,r] \;l\leq j,i\leq 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\n",ans);
return 0;
}
不摆烂了,写题