题目

思路

暴力很好打,我们显然可以先把关于 \(k\) 的式子拆开

先二项式展开,然后把外面的 \(m\) 乘进去,把 \(p\) 的分母 \(m\) 消去

\(K = (\sum_{i=1}^m (x_i - p)^2) \times m = m \times \sum_{i=1}^m x_i^2 - (\sum_{i=1}^m x_i)^2\)

发现它只剩下整数的乘和减运算

其实可以看出我们需要维护的东西:区间小于等于 \(z\) 的数的个数,这些数的和,这些数的平方的和

那么我们怎么维护区间小于等于 \(z\) 的数的信息呢?

对于这种二维偏序问题,经典的做法是在线的主席树

然而空间卡得不行不行的

所以我们考虑离线做法

依照题目意思,唯有 \(w \leq z\) 的数会对当前答案产生贡献

我们离线,先按照 \(w,z\) 从小到大排序

那么我们按这个顺序做下去,每遇到一个点就将其以它在原序列中的编号插入到某种数据结构中

遇到一个询问时,我们已经保证了 \(w \leq z\) 的数在这个数据结构中,只要查询区间 \([l..r]\) 的信息就好

因为空间的恶心,推荐使用树状数组

\(Code\)

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL; const int N = 4e5 + 5;
const LL INF = -1e18 - 1e15;
LL m , ps1 , ps2 , ans[N];
int n , q , h[N] , tot; struct question{
int to , nxt;
}c[N]; struct ask{
int x , y , z , id;
}a[N]; struct node{
int w , id;
LL pos;
}b[N]; struct segment{
int cnt;
LL pos1 , pos2;
}seg[N]; inline bool cmp1(node x , node y){return x.w < y.w;}
inline bool cmp2(ask x , ask y){return x.z < y.z;}
inline void addask(int id1 , int id2){c[++tot].to = id2 , c[tot].nxt = h[id1] , h[id1] = tot;}
inline int lowbit(int x){return x & (-x);} inline void update(int x , int ct , LL p1 , LL p2)
{
for(; x <= n; x += lowbit(x))
seg[x].cnt += ct , seg[x].pos1 += p1 , seg[x].pos2 += p2;
} inline void query(int x , int fl)
{
for(; x; x -= lowbit(x))
m += (LL)seg[x].cnt * fl , ps1 += seg[x].pos1 * fl , ps2 += seg[x].pos2 * fl;
} int main()
{
freopen("sequence.in" , "r" , stdin);
freopen("sequence.out" , "w" , stdout);
scanf("%d%d" , &n , &q);
for(register int i = 1; i <= n; i++) scanf("%d%lld" , &b[i].w , &b[i].pos) , b[i].id = i;
for(register int i = 1; i <= q; i++) scanf("%d%d%d" , &a[i].x , &a[i].y , &a[i].z) , a[i].id = i;
sort(b + 1 , b + n + 1 , cmp1) , sort(a + 1 , a + q + 1 , cmp2); int l , r , mid , res;
for(register int i = 1; i <= q; i++)
{
l = 1 , r = n , mid , res = 0;
while (l <= r)
{
mid = (l + r) >> 1;
if (b[mid].w <= a[i].z) res = mid , l = mid + 1;
else r = mid - 1;
}
if (res == 0) ans[a[i].id] = INF;
else addask(res , i);
}
for(register int i = 1; i <= n; i++)
{
update(b[i].id , 1 , b[i].pos , b[i].pos * b[i].pos);
for(register int j = h[i]; j; j = c[j].nxt)
{
int id = c[j].to;
ps1 = ps2 = 0 , m = 0;
query(a[id].y , 1) , query(a[id].x - 1 , -1);
if (m == 0)
{
ans[a[id].id] = INF;
continue;
}
ans[a[id].id] = m * ps2 - ps1 * ps1;
}
}
for(register int i = 1; i <= q; i++)
{
if (ans[i] == INF) printf("empty\n");
else printf("%lld\n" , ans[i]);
}
}

其实这题有个很暴力的方法

分块大法好!!!

我们维护一个分块数组

它包括每个点的 \(w,pos\)

然后同一块内的数按 \(w\) 从小到大排序

维护前缀和包括一次方和二次方的

查询只需要二分找块中的位置

前缀和更新即可

\(Code\)

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL; const int N = 4e5 + 5;
LL m , pos[N] , ps1 , ps2;
int n , q , w[N] , st[N] , ed[N] , num , belong[N]; struct node{
int w;
LL pos , pos1 , pos2;
}t[N]; inline bool cmp(node x , node y){return x.w < y.w;} inline void parepre()
{
num = (int)sqrt(n);
for(register int i = 1; i <= num; i++) st[i] = n / num * (i - 1) + 1 , ed[i] = n / num * i;
ed[num] = n;
for(register int i = 1; i <= num; i++)
{
for(register int j = st[i]; j <= ed[i]; j++) belong[j] = i , t[j] = (node){w[j] , pos[j] , 0 , 0};
sort(t + st[i] , t + ed[i] + 1 , cmp);
for(register int j = st[i]; j <= ed[i]; j++)
{
(j == st[i] ? (t[j].pos1 = t[j].pos) : (t[j].pos1 = t[j - 1].pos1 + t[j].pos));
(j == st[i] ? (t[j].pos2 = t[j].pos * t[j].pos) : (t[j].pos2 = t[j - 1].pos2 + t[j].pos * t[j].pos));
}
}
} inline void query(int l , int r , int z)
{
int x = belong[l] , y = belong[r];
if (x == y)
{
for(register int i = l; i <= r; i++)
if (w[i] <= z) m++ , ps1 += pos[i] , ps2 += pos[i] * pos[i];
return;
}
for(register int i = l; i <= ed[x]; i++)
if (w[i] <= z) m++ , ps1 += pos[i] , ps2 += pos[i] * pos[i];
for(register int i = st[y]; i <= r; i++)
if (w[i] <= z) m++ , ps1 += pos[i] , ps2 += pos[i] * pos[i];
int l1 , r1 , mid , ret;
for(register int i = x + 1; i <= y - 1; i++)
{
l1 = st[i] , r1 = ed[i] , ret = 0;
while (l1 <= r1)
{
mid = (l1 + r1) >> 1;
if (t[mid].w <= z) ret = mid , l1 = mid + 1;
else r1 = mid - 1;
}
if (ret) m += ret - st[i] + 1 , ps1 += t[ret].pos1 , ps2 += t[ret].pos2;
}
} int main()
{
freopen("sequence.in" , "r" , stdin);
freopen("sequence.out" , "w" , stdout);
scanf("%d%d" , &n , &q);
for(register int i = 1; i <= n; i++) scanf("%d%lld" , &w[i] , &pos[i]);
parepre();
int x , y , z;
while (q--)
{
scanf("%d%d%d" , &x , &y , &z);
ps1 = ps2 = 0 , m = 0;
query(x , y , z);
if (m == 0)
{
printf("empty\n");
continue;
}
LL k = m * ps2 - ps1 * ps1;
printf("%lld\n" , k);
}
}

JZOJ 4319. 【NOIP2015模拟11.5】Lucas的数列的更多相关文章

  1. [JZOJ 4307] [NOIP2015模拟11.3晚] 喝喝喝 解题报告

    题目链接: http://172.16.0.132/senior/#main/show/4307 题目: 解题报告: 题目询问我们没出现坏对的连续区间个数 我们考虑从左到有枚举右端点$r$,判断$a[ ...

  2. 【NOIP2015模拟11.5】JZOJ8月5日提高组T2 Lucas的数列

    [NOIP2015模拟11.5]JZOJ8月5日提高组T2 Lucas的数列 题目 PS:\(n*n*T*T<=10^{18}\)而不是\(10^1*8\) 题解 题意: 给出\(n\)个元素的 ...

  3. JZOJ 4298. 【NOIP2015模拟11.2晚】我的天

    4298. [NOIP2015模拟11.2晚]我的天 (File IO): input:ohmygod.in output:ohmygod.out Time Limits: 1000 ms Memor ...

  4. 【NOIP2015模拟11.5】JZOJ8月5日提高组T1 俄罗斯套娃

    [NOIP2015模拟11.5]JZOJ8月5日提高组T1 俄罗斯套娃 题目 题解 题意就是说 将1~\(n\)排列,问有多少种方案使得序列的逆序对个数小于\(k\) 很容易想到DP 设\(f[i][ ...

  5. 【NOIP2015模拟11.2晚】JZOJ8月4日提高组T2 我的天

    [NOIP2015模拟11.2晚]JZOJ8月4日提高组T2 我的天 题目 很久很以前,有一个古老的村庄--xiba村,村子里生活着n+1个村民,但由于历届村长恐怖而且黑暗的魔法统治下,村民们各自过着 ...

  6. 【NOIP2015模拟11.4】JZOJ2020年8月6日提高组T2 最优交换

    [NOIP2015模拟11.4]JZOJ2020年8月6日提高组T2 最优交换 题目 题解 题意 有一个长度为\(n\)的正整数 最多可以进行\(k\)次操作 每次操作交换相邻两个位置上的数 问可以得 ...

  7. 【NOIP2015模拟11.4】JZOJ8月6日提高组T1 刷题计划

    [NOIP2015模拟11.4]JZOJ8月6日提高组T1 刷题计划 题目 题解 题意 有\(n\)道题,编号为1~\(n\) 给出\(m\)次操作 每次操作有3种类型 1 \(x\) 表示交了\(A ...

  8. 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行

    [NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...

  9. 【NOIP2015模拟11.3】备用钥匙

    题目 你知道Just Odd Inventions社吗?这个公司的业务是"只不过是奇妙的发明(Just Odd Inventions)".这里简称为JOI社. JOI社有N名员工, ...

  10. JZOJ4307. 【NOIP2015模拟11.3晚】喝喝喝

    Description

随机推荐

  1. 解决一个mysql报错

    问题描述 insert into btsync (key,title) values ('a','b'); ERROR 1064 (42000): You have an error in your ...

  2. Springboot 2.3.1配置拦截器遇到的坑

    1.多个配置类继承WebConfigureSupport或实现WebConfigure接口导致拦截器失效 2.拦截器中的bean无法正常注入,SpringBoot项目的Bean装配默认规则是根据App ...

  3. 强化学习调参技巧二:DDPG、TD3、SAC算法为例:

    1.训练环境如何正确编写 强化学习里的 env.reset() env.step() 就是训练环境.其编写流程如下: 1.1 初始阶段: 先写一个简化版的训练环境.把任务难度降到最低,确保一定能正常训 ...

  4. 前端h5适配刘海屏和滴水屏

    前端适配苹果刘海屏,安卓刘海屏水滴瓶 其实w3c早就为我们提供了解决方法(CSS3新特性viewport-fit) 在w3c.org官方给出的关于圆形展示(Round display)的标准中, 提到 ...

  5. cmd命令行ssh连接Linux服务器

    打开cmd工具 使用命令ssh连接服务器 ssh 用户名@ip地址 (不需要指定端口号,默认端口就是22) 输入密码即可

  6. 2022年8月20,第一组,周鹏,从1到m中随机取n个数,n<=m,显示出所有取法

    static Random a1 =new Random(); static int m = a1.nextInt(20)+1;//随机取一个1到20的值 static int n = a1.next ...

  7. .NET6使用NLog向文件、数据库写数据

    1.Nuget 引入 NLog NLog.Web.AspNetCore NLog.Database(写入数据库使用) 2.创建nlog.config 注意数据库连接字符串需要配置TrustServer ...

  8. Java面试的一些面试题

    ​ 10<<2=? tip:10的二进制为1010,左移两位即:101000,换算为十进制为2的5次方加上2的三次方等于40 答:40 1.dr-xr-xr-r解释一下权限的含义 tip: ...

  9. ABC238E Range Sums

    简要题意 有一个长度为 \(N\) 的序列 \(a\),你知道 \(Q\) 个区间的和.求是否可以知道 \([1,n]\) 的和. \(1 \leq N,Q \leq 2 \times 10^5\) ...

  10. 【Java刷题】初始化List应该选择ArrayList还是LinkedList

    文章目录 前言 题目 解题思路 遇到的坑:ArrayList和LinkedList 未通过代码 通过代码 小结 ArrayList和LinkedList的区别 在刷题的时候应该如何选择 排序效率 测试 ...