Luogu P4901 排队 fib数列+树状数组+倍增
这题让我升华。。还好只重构了一遍
首先我们发现:$n$较小时,整个队伍的形态 跟 $n$ 比较大时的局部是一样的
所以我们预处理出这个队伍的形态,和每一行每个位置的质因子个数的前缀和,$O(nlogn)$,然后每次回答$log(n)$
方法:
1.线性筛,筛出每个数值因子的个数;
2.然后用一个树状数组,维护整个队列中的还存在的数的数量;相当于统计一个数组(设其为$a$)的前缀和,这个数组以自己为下标,存储这个数还存不存在,即$a[x]=1表示x存在,a[x]=0表示x不存在$;刚开始$a$中都为$1$,当某个数$x$被删除时,单点修改$a[x]=0$.
3.查询排名:这里要用到倍增的思路。因为当树状数组的下标$pos==2^k$时,它维护的是$[1,2^k]$的前缀和,所以根据树状数组的思想,可以倍增查找;
4.因为每次查询后都会删一个数,所以查询的实际位置是$fib[i]-已经删去的数的个数,即fib[i]-i+1$
5.最后对于每一个询问,在预处理出的 队伍形态 的数组的第$k$行中,查找编号小于但最接近$n$的那个数数的位置,对应到前缀和数组中的位置就是答案。
但是自己还有个疑问:为何空间开一半就够了。。。自己一直MLE,看了题解才开了一半qwq
PS:bitset比bool 快一些
代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<bitset>
#define R register int
const int N=,K=;
using namespace std;
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
int c[N+],fib[];
inline int lbt(int x) {return x&-x;}
inline void add(int pos,int vl) {for(;pos<=N;pos+=lbt(pos)) c[pos]+=vl;}
int pri[N/],tot;
short cnt[N+];
bitset<N+> vis;
inline void PRI() {
for(R i=;i<=N;++i) {
if(!vis[i]) pri[++tot]=i,cnt[i]=;
for(R j=;j<=tot&&i*pri[j]<=N;++j) {
vis[i*pri[j]]=true,cnt[i*pri[j]]=cnt[i]+;
if(i%pri[j]==) break;
}
}
}
vector<int> sum[K+],num[K+];
inline int query(int rk) {
R pos=,tot=; for(R t=;t>=;--t)
if(tot+c[pos+(<<t)]<rk) pos+=(<<t),tot+=c[pos];
return pos+;
}
inline void PRE() { PRI(); fib[]=,fib[]=;
for(R i=;i<=;++i) fib[i]=fib[i-]+fib[i-];
for(R i=;i<=N;++i) add(i,); R tot=N;
for(R i=;i<=K;++i) for(R j=;fib[j]-j+<=tot;++j) {
R pos=query(fib[j]-j+); add(pos,-),--tot; //cout<<pos<<" "<<cnt[pos]; putchar('\n');
if(j>=) sum[i].push_back(sum[i][j-]+cnt[pos]);
else sum[i].push_back(cnt[pos]);
num[i].push_back(pos);
}
}
signed main() { PRE(); R t=g();
for(R i=;i<=t;++i) {
R n=g(),k=g(); if(num[k][]>n) {printf("-1\n"); continue;}
R pos=upper_bound(num[k].begin(),num[k].end(),n)-num[k].begin()-;
printf("%d\n",sum[k][pos]);
} //while(1);
}
2019.05.17
Luogu P4901 排队 fib数列+树状数组+倍增的更多相关文章
- 【bzoj2819】Nim DFS序+树状数组+倍增LCA
题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...
- [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)
[NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...
- 【BZOJ】1699: [Usaco2007 Jan]Balanced Lineup排队(rmq/树状数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=1699 我是用树状数组做的..rmq的st的话我就不敲了.. #include <cstdio& ...
- 题解报告:Luogu P3368 【模板】树状数组 2(区间修改,单点查询)
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...
- [luogu]P2657低头一族[树状数组]
[luogu]P2657 低头一族 题目描述 一群青年人排成一队,用手机互相聊天. 每个人的手机有一个信号接收指标,第i个人的接收指标设为v[i]. 如果位置在x[i]的人要和位置在xj的人聊天,那么 ...
- Luogu P3374 【模板】树状数组 1
真正的模板题. 树状数组的思想很简单(不如说背代码更简单),每个节点记录多个节点的信息(每个点存x&(-x)个). 道理可以参见很多大佬的博客,最后前缀和的思想搞一下就好了.不想说也不会说. ...
- bzoj2141: 排队(分块+树状数组)
块套树为什么会这么快.. 先跑出原序列逆序对. 显然交换两个位置$l,r$,对$[1,l),(r,n]$里的数没有影响,所以只需要考虑$[l,r]$内的数. 设$(l,r)$内的数$a_i$,则按以下 ...
- 【Luogu】P2617Dynamic Ranking(树状数组套主席树)
题目链接 树状数组套主席树有点难懂qwq 不好理解 树状数组套主席树的直观理解应该是:树状数组的每一个节点是一棵主席树. 普通区间修改我们是创建1个线段树,树状数组套主席树的时候我们就创建log个线段 ...
- BZOJ 2141 排队(分块+树状数组)
题意 第一行为一个正整数n,表示小朋友的数量:第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高:第三行为一个正整数m,表示交换操作的次数:以下m行每行包含两个正整数 ...
随机推荐
- 反编译工具Reflector下载(集成FileGenerator和FileDisassembler)
Reflector是一款比较强大的反编译工具,相信很多朋友都用过它,但reflector本身有很多局限性, 比如只能一个一个的查看方法等,但幸好reflector支持插件功能目前网上有很多reflec ...
- 找工作-——网络IO
网络层 主要任务是把网络协议数据单元或分组从源计算机经过适当的路径发送到目的地计算机.从源计算机到目的计算机可能要经过若干个中间节点,这需要在通信子网中进行路由选择. 网络层与数据链路层有很大的差别, ...
- rufus-scheduler定时任务示例代码
require 'rubygems' require 'rufus/scheduler' scheduler = Rufus::Scheduler.start_new scheduler.in '20 ...
- NW.js将网站打包成桌面应用
需求:已有一个网站,因为浏览器兼容性等问题,想自己封装一个浏览器,打开时固定打开这个网站,通过这样的封装,将网站变成桌面应用程序. 1. 下载并安装NW.js的最新稳定版本(NW.js) 2. 创建一 ...
- Postman(调试工具)
Postman Postman用法简介-Http请求模拟工具 时间 2015-09-26 23:52:00 博客园-原创精华区 原文 http://www.cnblogs.com/codingbl ...
- Lua中的点、冒号与self
Lua中的点.冒号与self,它们之间的关系主要体现在函数的定义与调用上,Lua在函数定义时可以用点也可以用冒号,如: function mytable.fun(p) return p end fun ...
- 应用程序无法正常启动提示错误0xc000007b 问题的原因和解决方法
应用程序无法正常启动提示错误0xc000007b 问题的原因和解决方法 前提条件: 你使用的是VS201x软件编写程序,你使用的电脑是X64位的,并且你在使用OpenCV库.你编写的程序可以正常编译, ...
- hadoop-2.3.0-cdh5.1.0完全分布式搭建(基于centos)
先参考:<hadoop-2.3.0-cdh5.1.0伪分布安装(基于centos)> http://blog.csdn.net/jameshadoop/article/details/39 ...
- eclipse 远程操作HIVE
首先启动HiveServer hive --service hiveserver 10000 & 创建工程 引入包: 代码(简单的查询): package com.hive.jdbc; imp ...
- 6.【应急响应】Linux入侵排查思路
0x01 入侵排查思路 一.账号安全 基本使用: 1.用户信息文件/etc/passwd root:x:0:0:root:/root:/bin/bash account:password:UID:GI ...