【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 K=(i=1m(xip)2)m
( x i − p ) 2 (x_{i}-p)^2 (xip)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=1m(xi2xipxip+p2))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 K=(i=1m(xi22xip+p2))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 K=(i=1mxi2)m2(i=1mxi)pm+p2m2
A = ∑ i = 1 m x i 2 A=\sum^{m}_{i=1}x_{i}^2 A=i=1mxi2, B = ∑ i = 1 m x i B=\sum^{m}_{i=1}x_{i} B=i=1mxi
那么整个式子就变成了 K = A m − 2 ∗ B ∗ p ∗ m + p 2 ∗ m 2 K=Am-2*B*p*m+p^2*m^2 K=Am2Bpm+p2m2
又知道 p = ∑ i = 1 m x i m p=\frac{\sum^{m}_{i=1}x_{i}}{m} p=mi=1mxi,即 p = B m p=\frac{B}{m} p=mB
再把这个式子带入,得
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=Am2BmBm+(mB)2m2
再化简,得 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=Am2mB2m+m2B2m2
K = A m − 2 B 2 + B 2 K=Am-2B^2+B^2 K=Am2B2+B2
K = A m − B 2 K=Am-B^2 K=AmB2
可以考虑离线的做法。
首先把所有元素按照 w i w_{i} wi排序,所有询问按照 z z z排序。
这样我们就可以枚举询问,然后把 w i w_{i} wi小于等于 z z z的元素全部插入进一个树状数组里。由于上面已经把式子化简了,所以呢我们就可以只记录 A A A B B B m m m,不需要算出 p 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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值