1. 程式人生 > 實用技巧 >習題:Scalar Queries(線段樹)

習題: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;
}