Educational Codeforces Round 171 (Rated for Div. 2)
ABC 略
D
l和r太大导致我们只能把它们映射到某个小区间内去求。以a1 a2 ...an开头加一共有n个区间,我们把l和r映射到这个区间求。我们只要确定l和r在区间中的位置,就可以O(1)利用区间的前缀和求出每个询问,区间的和由原数列的前缀和的前缀和求出。最后只需处理不满一个完整区间的情况即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10;
int T,n,q,a[N],s[N],ss[N],ass[N],l1,r1,l,r,x1,y3,x2,y2,ans,w[N],asss[N];
void init()
{
}
int XX(int x,int y)
{return ss[x+y-1]-ss[x-1]-y*s[x-1];
}
void solve()
{cin>>n;init();for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];for(int i=1;i<=n;i++) ss[i]=ss[i-1]+s[i];for(int i=1;i<=n;i++) ass[i]=(ss[n]-ss[i-1])-(n-i+1)*s[i-1];for(int i=1;i<=n;i++) asss[i]=asss[i-1]+ass[i];cin>>q;for(int i=1;i<=q;i++){ans=0;cin>>l1>>r1;l=0,r=n;while(l<=r){int mid=(l+r)/2;if((n+n-mid+1)*mid/2<=l1){x1=mid;l=mid+1;}else r=mid-1;}y3=l1-(n+n-x1+1)*x1/2;l=0,r=n;while(l<=r){int mid=(l+r)/2;if((n+n-mid+1)*mid/2<=r1){x2=mid;l=mid+1;}else r=mid-1;}y2=r1-(n+n-x2+1)*x2/2;if(x1==n) y3=1;else{if(y3) x1++;else y3=n-x1+1;}if(x2==n) y2=1;else{if(y2) x2++;else y2=n-x2+1;}if(x1==x2){ans=XX(x1,y2)-XX(x1,y3-1);cout<<ans<<"\n";}else if(x2==x1+1){ans=ass[x1]-XX(x1,y3-1)+XX(x2,y2);cout<<ans<<"\n";}else{ans=ass[x1]-XX(x1,y3-1)+XX(x2,y2);ans+=asss[x2-1]-asss[x1];cout<<ans<<"\n";}}
}
signed main()
{std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);//cin>>T;T=1;while(T--) solve();
}