习题:Scalar Queries(线段树)
题目
思路
如果固定左端点,算出所有右端点可能的情况,这个用线段树可以很容易的\(O(n*log)\)的搞定
考虑左端点往右移一次的情况,即删除\(a_i\)的情况,
对于\(a_j>a_i\)的情况,\(a_i\)会把每一个\(a_j\)的排名垫高1,次数为\(n-j+1\),很容易用线段树维护
对于\(a_j<a_i\)的情况,每一个\(a_j\)会把\(a_i\)的排名垫高1,次数为\(n-j+1\),这个也很容易用线段树维护,
代码
#include<iostream>
#include<cstdio>
using namespace std;
const int mod=1e9+7;
namespace my_IO
{
void read(int &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void read(long long &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void write(int x)
{
if(x<10)
putchar(x%10+'0');
else
{
write(x/10);
putchar(x%10+'0');
}
}
void write(long long x)
{
if(x<10)
putchar(x%10+'0');
else
{
write(x/10);
putchar(x%10+'0');
}
}
}
namespace lst
{
#define pii pair<int,int>
#define x first
#define y second
int cnt=1;
struct node
{
int lson,rson;
pii val;//x为n-i+1,y为(n-i+1)*a[i]
long long s,siz;
}tre[7000005];
pii operator + (const pii &a,const pii &b)
{
return make_pair((a.x+b.x)%mod,(a.y+b.y)%mod);
}
int change(int pos,pii val,int l=1,int r=1000000000,int k=1)
{
if(l>pos||pos>r)
return k;
if(k==0)
k=++cnt;
if(l==r)
{
tre[k].siz=1;
tre[k].val=tre[k].val+val;
tre[k].s=(tre[k].s+pos)%mod;
return k;
}
int mid=(l+r)>>1;
tre[k].lson=change(pos,val,l,mid,tre[k].lson);
tre[k].rson=change(pos,val,mid+1,r,tre[k].rson);
tre[k].val=tre[tre[k].lson].val+tre[tre[k].rson].val;
tre[k].s=(tre[tre[k].lson].s+tre[tre[k].rson].s)%mod;
tre[k].siz=tre[tre[k].lson].siz+tre[tre[k].rson].siz;
return k;
}
void delet(int pos,int l=1,int r=1000000000,int k=1)
{
if(l>pos||pos>r)
return;
if(l==r)
{
tre[k].val.x=tre[k].val.y=tre[k].s=tre[k].siz=0;
return;
}
int mid=(l+r)>>1;
delet(pos,l,mid,tre[k].lson);
delet(pos,mid+1,r,tre[k].rson);
tre[k].val=tre[tre[k].lson].val+tre[tre[k].rson].val;
tre[k].s=(tre[tre[k].lson].s+tre[tre[k].rson].s)%mod;
tre[k].siz=tre[tre[k].lson].siz+tre[tre[k].rson].siz;
}
int ask_siz(int ql,int qr,int l=1,int r=1000000000,int k=1)//求个数
{
if(ql>r||l>qr||k==0)
return 0;
if(ql<=l&&r<=qr)
return tre[k].siz;
int mid=(l+r)>>1;
return ask_siz(ql,qr,l,mid,tre[k].lson)+ask_siz(ql,qr,mid+1,r,tre[k].rson);
}
long long ask_s(int ql,int qr,int l=1,int r=1000000000,int k=1)//算和
{
if(ql>r||l>qr||k==0)
return 0;
if(ql<=l&&r<=qr)
return tre[k].s;
int mid=(l+r)>>1;
return (ask_s(ql,qr,l,mid,tre[k].lson)+ask_s(ql,qr,mid+1,r,tre[k].rson))%mod;
}
long long ask1(int ql,int qr,int l=1,int r=1000000000,int k=1)
{
if(ql>r||l>qr||k==0)
return 0;
if(ql<=l&&r<=qr)
return tre[k].val.x;
int mid=(l+r)>>1;
return (ask1(ql,qr,l,mid,tre[k].lson)+ask1(ql,qr,mid+1,r,tre[k].rson))%mod;
}
long long ask2(int ql,int qr,int l=1,int r=1000000000,int k=1)
{
if(ql>r||l>qr||k==0)
return 0;
if(ql<=l&&r<=qr)
return tre[k].val.y;
int mid=(l+r)>>1;
return (ask2(ql,qr,l,mid,tre[k].lson)+ask2(ql,qr,mid+1,r,tre[k].rson))%mod;
}
}
using namespace my_IO;
using namespace lst;
int n;
long long a[500005];
long long ans,now,temp;
int main()
{
read(n);
for(int i=1;i<=n;i++)
{
read(a[i]);
temp=(temp+a[i]*(ask_siz(1,a[i]-1)+1)%mod+ask_s(a[i]+1,1000000000))%mod;
now=(now+temp)%mod;
change(a[i],make_pair(n-i+1,(n-i+1)*a[i]%mod));
}
ans=now;
for(int i=1;i<n;i++)
{
now=((now-ask1(1,a[i]-1)*a[i]%mod-ask2(a[i]+1,1000000000)-(n-i+1)*a[i]%mod)%mod+mod)%mod;
ans=(ans+now)%mod;
delet(a[i]);
}
write(ans);
return 0;
}

浙公网安备 33010602011771号