習題:Scalar Queries(線段樹)
阿新 • • 發佈:2020-08-24
題目
思路
如果固定左端點,算出所有右端點可能的情況,這個用線段樹可以很容易的\(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; }