Description
Solution
首先我们把整个式子化简一下:
把
拆开,可以得到
也就是
再把sigama拆开,就可以得到
令
,
那么整个式子就变成了
又知道
,即
再把这个式子带入,得
再化简,得
即
可以考虑离线的做法。
首先把所有元素按照
排序,所有询问按照
排序。
这样我们就可以枚举询问,然后把
小于等于
的元素全部插入进一个树状数组里。由于上面已经把式子化简了,所以呢我们就可以只记录
、
和
,不需要算出
,再区间查询即可。
Code
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N=4e5+5;
int n,m,q0=1,q1=1;
ll ans[N],c[N][3];
struct node {int w,num;ll pos;}a[N];
struct rec {int x,y,z,num;}q[N];
bool cmp(node x,node y) {return x.w<y.w;}
bool cmp1(rec x,rec y) {return x.z<y.z;}
ll lowbit(int x) {return x&-x;}
void update(int x,ll val) {
while(x<=n) {
c[x][0]+=val;
c[x][1]+=val*val;
c[x][2]++;
x+=lowbit(x);
}
}
ll query(int x,int y) {
ll A=0,cnt=0,B=0;
while(x>0) {
A+=c[x][0];
B+=c[x][1];
cnt+=c[x][2];
x-=lowbit(x);
}
while(y>0) {
A-=c[y][0];
B-=c[y][1];
cnt-=c[y][2];
y-=lowbit(y);
}
if(!cnt)return -1;
return B*cnt-A*A;
}
int main() {
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%d%lld",&a[i].w,&a[i].pos);
a[i].num=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=m;i++) {
scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z);
q[i].num=i;
}
sort(q+1,q+1+m,cmp1);
while(q1<=m) {
while(q0<=n&&a[q0].w<=q[q1].z) {
update(a[q0].num,a[q0].pos);
q0++;
}
ans[q[q1].num]=query(q[q1].y,q[q1].x-1);
q1++;
}
for(int i=1;i<=m;i++)
if(ans[i]==-1)puts("empty");
else printf("%lld\n",ans[i]);
fclose(stdin);
fclose(stdout);
return 0;
}