【NOIP2015模拟11.5】Lucas的数列题解

Description

在这里插入图片描述

Solution

首先我们把整个式子化简一下:
K = ( i = 1 m ( x i p ) 2 ) m K=(\sum^{m}_{i=1}(x_{i}-p)^2)*m
( x i p ) 2 (x_{i}-p)^2 拆开,可以得到
K = ( i = 1 m ( x i 2 x i p x i p + p 2 ) ) m K=(\sum^{m}_{i=1}(x_{i}^2-x_{i}*p-x_{i}*p+p^2))*m
也就是 K = ( i = 1 m ( x i 2 2 x i p + p 2 ) ) m K=(\sum^{m}_{i=1}(x_{i}^2-2*x_{i}*p+p^2))*m
再把sigama拆开,就可以得到
K = ( i = 1 m x i 2 ) m 2 ( i = 1 m x i ) p m + p 2 m 2 K=(\sum^{m}_{i=1}x_{i}^2)*m-2*(\sum^{m}_{i=1}x_{i})*p*m+p^2*m^2
A = i = 1 m x i 2 A=\sum^{m}_{i=1}x_{i}^2 , B = i = 1 m x i B=\sum^{m}_{i=1}x_{i}
那么整个式子就变成了 K = A m 2 B p m + p 2 m 2 K=Am-2*B*p*m+p^2*m^2
又知道 p = i = 1 m x i m p=\frac{\sum^{m}_{i=1}x_{i}}{m} ,即 p = B m p=\frac{B}{m}
再把这个式子带入,得
K = A m 2 B B m m + ( B m ) 2 m 2 K=Am-2B\frac{B}{m}*m+(\frac{B}{m})^2*m^2
再化简,得 K = A m 2 B 2 m m + B 2 m 2 m 2 K=Am-2\frac{B^2}{m}*m+\frac{B^2}{m^2}*m^2
K = A m 2 B 2 + B 2 K=Am-2B^2+B^2
K = A m B 2 K=Am-B^2
可以考虑离线的做法。
首先把所有元素按照 w i w_{i} 排序,所有询问按照 z z 排序。
这样我们就可以枚举询问,然后把 w i w_{i} 小于等于 z z 的元素全部插入进一个树状数组里。由于上面已经把式子化简了,所以呢我们就可以只记录 A A B B m m ,不需要算出 p p ,再区间查询即可。

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;
}

猜你喜欢

转载自blog.csdn.net/MZHjr/article/details/107824110