JZOJ 4319. 【NOIP2015模拟11.5】Lucas的数列
题目
思路
暴力很好打,我们显然可以先把关于 \(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的数列的更多相关文章
- [JZOJ 4307] [NOIP2015模拟11.3晚] 喝喝喝 解题报告
题目链接: http://172.16.0.132/senior/#main/show/4307 题目: 解题报告: 题目询问我们没出现坏对的连续区间个数 我们考虑从左到有枚举右端点$r$,判断$a[ ...
- 【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\)个元素的 ...
- JZOJ 4298. 【NOIP2015模拟11.2晚】我的天
4298. [NOIP2015模拟11.2晚]我的天 (File IO): input:ohmygod.in output:ohmygod.out Time Limits: 1000 ms Memor ...
- 【NOIP2015模拟11.5】JZOJ8月5日提高组T1 俄罗斯套娃
[NOIP2015模拟11.5]JZOJ8月5日提高组T1 俄罗斯套娃 题目 题解 题意就是说 将1~\(n\)排列,问有多少种方案使得序列的逆序对个数小于\(k\) 很容易想到DP 设\(f[i][ ...
- 【NOIP2015模拟11.2晚】JZOJ8月4日提高组T2 我的天
[NOIP2015模拟11.2晚]JZOJ8月4日提高组T2 我的天 题目 很久很以前,有一个古老的村庄--xiba村,村子里生活着n+1个村民,但由于历届村长恐怖而且黑暗的魔法统治下,村民们各自过着 ...
- 【NOIP2015模拟11.4】JZOJ2020年8月6日提高组T2 最优交换
[NOIP2015模拟11.4]JZOJ2020年8月6日提高组T2 最优交换 题目 题解 题意 有一个长度为\(n\)的正整数 最多可以进行\(k\)次操作 每次操作交换相邻两个位置上的数 问可以得 ...
- 【NOIP2015模拟11.4】JZOJ8月6日提高组T1 刷题计划
[NOIP2015模拟11.4]JZOJ8月6日提高组T1 刷题计划 题目 题解 题意 有\(n\)道题,编号为1~\(n\) 给出\(m\)次操作 每次操作有3种类型 1 \(x\) 表示交了\(A ...
- 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行
[NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...
- 【NOIP2015模拟11.3】备用钥匙
题目 你知道Just Odd Inventions社吗?这个公司的业务是"只不过是奇妙的发明(Just Odd Inventions)".这里简称为JOI社. JOI社有N名员工, ...
- JZOJ4307. 【NOIP2015模拟11.3晚】喝喝喝
Description
随机推荐
- CSS伪类使用详解
基本描述 CSS伪类是很常用的功能,主要应用于选择器的关键字,用来改变被选择元素的特殊状态下的样式. 伪类类似于普通CSS类的用法,是对CSS选择器的一种扩展,增强选择器的功能. 目前可用的伪类有大概 ...
- [论文阅读] 颜色迁移-Correlated Color Space
[论文阅读] 颜色迁移-Correlated Color Space 文章: Color transfer in correlated color space, [paper], [matlab co ...
- 推荐一款采用 .NET 编写的 反编译到源码工具 Reko
今天给大家介绍的是一款名叫Reko的开源反编译工具,该工具采用C#开发,广大研究人员可利用Reko来对机器码进行反编译处理.我们知道.NET 7 有了NativeAOT 的支持,采用NativeAOT ...
- pycharm恢复删除文档与查询修改前数据
1.pycharm恢复删除文档 第一步: 第二步: 2.pycharm查询修改前文档数据 第一步: 第二步:
- Django 连接各数据库配置汇总(sqlite3,MySql,Oracle)
在django中,默认配置的数据库是 sqlite3 # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#database ...
- Spring IOC官方文档学习笔记(二)之Bean概述
1.Bean概述 (1) Spring IoC容器管理一个或多个bean,这些bean是根据我们所提供的配置元数据来创建的,在容器内部,BeanDefinition对象就代表了bean的配置元数据,它 ...
- AcWing1137. 选择最佳线路
题目传送门 题目大意 \(\qquad\)有一张有向图,可以有若干个起点,只有一个终点,求所有起点到终点的最短路中最短的一条,若所有起点都与终点不连通,则输出\(-1\) 解题思路 \(\qquad\ ...
- 第一章 --------------------WPF基础概述
1.在使用WPF之前我一直在思考为什么要使用WPF? 主要原因在于我已经受够了MFC和Winform 和QT的界面设计.尤其是MFC的界面设计,使用一个界面库十分的复杂,并且我的绝大多数时间都是用在这 ...
- SpringBoot基础学习笔记
Springboot框架: springboot官网参考 Sringboot是整合spring技术栈的一站式框架,其简化配置,实现了自动化配置 Springboot基础结构: 1.pom.xml文件: ...
- wsl2 kali修改语言
直接执行sudo dpkg-reconfigure locales 会提示 dpkg-query: package 'locales' is not installed and no informat ...