洛谷 P5501 [LnOI2019]来者不拒,去者不追
题目描述
给定长度为 \(n\) 的序列 \(a\),给出 \(m\) 个询问。
对于每个询问,给出一个区间 \([l,r]\),求
\[\sum_{i=l}^{r}{\left(1+\sum_{j=l}^{r}{[a_j<a_i]}\right)a_i}
\]
数据范围:\(1\le n,m\le 5\times 10^5\),\(a_i\le 10^5\),\(1\le l \le r \le n\)。
时间范围:\(3000\operatorname{ms}\)。
Solution 1
看题目可以发现是求区间排名,求区间和显然不好在线维护,考虑莫队。
对于已有的区间 \([l,r]\),若向右插入一个元素,贡献为
\[\sum_{i=l}^{r}{[a_i>a_{r+1}]a_i}+a_{r+1}\left(1+\sum_{i=l}^{r}{[a_i<a_{r+1}]}\right)
\]
直接维护的复杂度为 \(\Theta(n\sqrt n\log a_{\max})\),期望得分 \(10\operatorname{pts}\)。
Solution 2
上边的带 \(\log\) 莫队是没有前途的,考虑二次离线。
考虑前缀和,向右插入一个元素,贡献为
\[\sum_{i=1}^{r}{[a_i>a_{r+1}]a_i}+a_{r+1}\left(1+\sum_{i=1}^{r}{[a_i<a_{r+1}]}\right)-\sum_{i=1}^{l-1}{[a_i>a_{r+1}]a_i}-a_{r+1}\left(\sum_{i=1}^{l-1}{[a_i<a_{r+1}]}\right)
\]
定义 \(f_{r}=\sum_{i=1}^{r-1}{[a_i>a_{r}]a_i}+a_{r}\left(1+\sum_{i=1}^{r-1}{[a_i<a_{r}]}\right)\),则贡献变为
\[f_{r+1}-\sum_{i=1}^{l-1}{[a_i>a_{r+1}]a_i}-a_{r+1}\left(\sum_{i=1}^{l-1}{[a_i<a_{r+1}]}\right)
\]
将 \(f\) 数组预处理出来前缀和,后边的贡献离线下来维护,套上值域分块即可处理。
向左插入同理。
由于 \(n,m\) 同阶,时间复杂度为 \(\Theta(n\sqrt n+n\sqrt{a_\max})\),期望得分 \(100\operatorname{pts}\)。
Code
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=500010;
typedef long long LL;
int K[maxn],L[maxn],R[maxn],T;
template<class T>inline void read(T &x){
x=0;char c;
do c=getchar();while(c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
}
template<class T>inline void write(T x){
static char stk[22];int top=0;
while(x)stk[++top]=x-x/10*10+48,x/=10;
while(top)putchar(stk[top--]);
putchar('\n');
}
struct query{
int l,r,id;
inline bool operator<(const query &qu)const{
return K[l]!=K[qu.l]?l<qu.l:((K[l]&1)?r<qu.r:r>qu.r);
}
}q[maxn];
struct Range{
int l,r,id,d;
inline Range(int _l=0,int _r=0,int _id=0,int _d=0){
l=_l;r=_r;id=_id;d=_d;
}
};
vector<Range> range[maxn];
struct TreeArray{
#define lowbit(x) (x&-x)
LL tr[maxn];
inline void add(int x,int d){while(x<=100000)tr[x]+=d,x+=lowbit(x);}
inline LL ask(int x){LL ans=0;while(x)ans+=tr[x],x-=lowbit(x);return ans;}
inline void clear(){memset(tr,0,sizeof(tr));}
#undef lowbit
}BIT;
LL f[maxn],pre[maxn];
struct BlockOfRange{
int bl[maxn],br[maxn],bk[maxn],kt;
LL v[maxn],tag[maxn],sum;
inline void Init(){
kt=sqrt(100010);
for(int i=1;i<=kt;++i)bl[i]=br[i-1]+1,br[i]=br[i-1]+kt;
if(R[kt]<100010)bl[kt+1]=br[kt]+1,br[++kt]=100010;
for(int i=1;i<=kt;++i)for(int j=bl[i];j<=br[i];++j)bk[j]=i;
}
inline void add(int x,int d){
int k=bk[x];sum+=d;
for(int i=x;i<=br[k];++i)v[i]+=d;
for(int i=k+1;i<=kt;++i)tag[i]+=d;
}
inline LL ask(int x){return tag[bk[x]]+v[x];}
inline void clear(){
memset(v,0,sizeof(v));
memset(tag,0,sizeof(tag));
sum=0;
}
}BOR1,BOR2;
LL ans[maxn],res[maxn];
int n,m,a[maxn];
int main(){
BOR1.Init();BOR2.Init();
read(n);read(m);
T=sqrt(n);
for(int i=1;i<=T;++i)L[i]=R[i-1]+1,R[i]=R[i-1]+T;
if(R[T]<n)L[T+1]=R[T]+1,R[T]=n;
for(int i=1;i<=T;++i)for(int j=L[i];j<=R[i];++j)K[j]=i;
for(int i=1;i<=n;++i)read(a[i]);
for(int i=1;i<=m;++i){read(q[i].l),read(q[i].r);q[i].id=i;}
sort(q+1,q+m+1);
for(int i=1;i<=n;++i){
f[i]=BIT.ask(a[i]);
BIT.add(1,a[i]);BIT.add(a[i],-a[i]);
}
BIT.clear();
for(int i=1;i<=n;++i){
f[i]+=(BIT.ask(a[i]-1)+1)*a[i];
BIT.add(a[i],1);
}
for(int i=1;i<=n;++i)pre[i]=pre[i-1]+f[i];
int curl=1,curr=0;
for(int i=1;i<=m;++i){
int l=q[i].l,r=q[i].r;
if(curr<r)range[curl-1].push_back(Range(curr+1,r,i,-1)),ans[i]+=pre[r]-pre[curr];
if(curr>r)range[curl-1].push_back(Range(r+1,curr,i,1)),ans[i]-=pre[curr]-pre[r];
curr=r;curl=l;
}
for(int i=1;i<=n;++i){
BOR1.add(a[i],a[i]);BOR2.add(a[i],1);
for(auto qry:range[i]){
int l=qry.l,r=qry.r,id=qry.id,d=qry.d;
for(int j=l;j<=r;++j)ans[id]+=(BOR1.sum-BOR1.ask(a[j])+a[j]*BOR2.ask(a[j]-1))*d;
}
}
for(int i=1;i<=n;++i)range[i].clear();BOR1.clear();BOR2.clear();BIT.clear();
for(int i=n;i;--i){
f[i]=BIT.ask(a[i]);
BIT.add(1,a[i]);BIT.add(a[i],-a[i]);
}
BIT.clear();
for(int i=n;i;--i){
f[i]+=(BIT.ask(a[i]-1)+1)*a[i];
BIT.add(a[i],1);
}
for(int i=n;i;--i)pre[i]=pre[i+1]+f[i];
curl=1;
for(int i=1;i<=m;++i){
int l=q[i].l,r=q[i].r;
if(curl<l)range[r+1].push_back(Range(curl,l-1,i,1)),ans[i]-=pre[curl]-pre[l];
if(curl>l)range[r+1].push_back(Range(l,curl-1,i,-1)),ans[i]+=pre[l]-pre[curl];
curl=l;
}
for(int i=n;i;--i){
BOR1.add(a[i],a[i]);BOR2.add(a[i],1);
for(auto qry:range[i]){
int l=qry.l,r=qry.r,id=qry.id,d=qry.d;
for(int j=l;j<=r;++j)ans[id]+=(BOR1.sum-BOR1.ask(a[j])+a[j]*BOR2.ask(a[j]-1))*d;
}
}
for(int i=2;i<=m;++i)ans[i]+=ans[i-1];
for(int i=1;i<=m;++i)res[q[i].id]=ans[i];
for(int i=1;i<=m;++i)write(res[i]);
return 0;
}

浙公网安备 33010602011771号