BZOJ5319: [Jsoi2018]军训列队
BZOJ5319: [Jsoi2018]军训列队
https://lydsy.com/JudgeOnline/problem.php?id=5319
分析:
- 易知把所有人按原本的顺序放到\([K,K+len-1]\)这些位置上是最优的。
- 我们只需要求一个\(mid\), 满足从\(mid\)以后的人都是向左移动。
- 这个可以用二分+主席树在\(O(nlog^2)\)的时间内解决, 然后过不去。
- 变成直接在主席树上二分就好了,需要一点小技巧。
- 即二分走的区间不一定包含答案点,但可能是答案点减\(1\), 在叶子上特判即可。
代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long ll;
#define N 500050
#define M 1500000
int n,m,a[N];
int siz[N*30],ls[N*30],rs[N*30],cnt,root[N];
ll sum[N*30];
void update(int l,int r,int x,int &p,int q) {
p=++cnt; ls[p]=ls[q]; rs[p]=rs[q]; siz[p]=siz[q]+1; sum[p]=sum[q]+x;
if(l==r) return ;
int mid=(l+r)>>1;
if(x<=mid) update(l,mid,x,ls[p],ls[q]);
else update(mid+1,r,x,rs[p],rs[q]);
}
ll c,now,s[N];
ll S(ll l,ll r) {return (l+r)*(r-l+1)/2;}
ll query(int l,int r,int p,int q) {
if(l==r) {
if(siz[p]>siz[q]&&l<now) {c++; return l;}
else return 0;
}
int mid=(l+r)>>1,sizls=siz[ls[p]]-siz[ls[q]];
if(!sizls) return query(mid+1,r,rs[p],rs[q]);
if(mid<=now+sizls-1) {
c+=sizls, now+=sizls;
return query(mid+1,r,rs[p],rs[q])+sum[ls[p]]-sum[ls[q]];
}else return query(l,mid,ls[p],ls[q]);
}
int main() {
scanf("%d%d",&n,&m);
int i,l,r,k;
for(i=1;i<=n;i++) scanf("%d",&a[i]),s[i]=s[i-1]+a[i],update(1,M,a[i],root[i],root[i-1]);
while(m--) {
scanf("%d%d%d",&l,&r,&k);
now=k; c=0;
ll tot=query(1,M,root[r],root[l-1]);
ll ans=S(k,k+c-1)-tot + s[r]-s[l-1]-tot-S(k+c,k+r-l);
printf("%lld\n",ans);
}
}
BZOJ5319: [Jsoi2018]军训列队的更多相关文章
- 【BZOJ5319】军训列队(主席树)
[BZOJ5319]军训列队(主席树) 题面 BZOJ 洛谷 题解 一眼题既视感... 首先很明显,每次询问的结果显然是做一次离散. 然后直接上主席树就好了... 查询答案的方式也很简单 考虑一下那个 ...
- [JSOI2018]军训列队
[JSOI2018]军训列队 题目大意: \(n(n\le5\times10^5)\)个学生排成一排,第\(i\)个学生的位置为\(a_i\).\(m(m\le5\times10^5)\)次命令,每次 ...
- BZOJ5319 & 洛谷4559 & LOJ2551:[JSOI2018]军训列队——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5319 https://www.luogu.org/problemnew/show/P4559 ht ...
- BZOJ.5319.[JSOI2018]军训列队(主席树)
LOJ BZOJ 洛谷 看错了,果然不是\(ZJOI\)..\(jry\)给\(JSOI\)出这么水的题做T3么= = 感觉说的有点乱,不要看我写的惹=-= 对于询问\(l,r,k\),设\(t=r- ...
- 洛谷 P4559: bzoj 5319: [JSOI2018]军训列队
题目传送门:洛谷 P4559. 题意简述: 有 \(n\) 个学生,编号为 \(i\) 的学生有一个位置 \(a_i\). 有 \(m\) 个询问,每次询问编号在 \([l,r]\) 区间内的学生跑到 ...
- bzoj 5319: [Jsoi2018]军训列队
Description Solution 最优情况可以是所有人按位置从小到大排序之后依次占到自己 \(K+\) 排名的位置上去 因为每一个休息位置不同,那么一定递增,所以一定存在一个分界点,左边的是往 ...
- BZOJ5319/LOJ2551「JSOI2018」列队
问题描述 作为一名大学生,九条可怜在去年参加了她人生中的最后一次军训. 军训中的一个重要项目是练习列队,为了训练学生,教官给每一个学生分配了一个休息位置.每次训练开始前,所有学生都在各自的休息位置休息 ...
- BZOJ5319 JSOI2018列队(主席树)
显然集合后相对位置不变最优.主席树上二分向左和向右的分界点即可.注意主席树的值域.我怎么天天就写点一眼题啊. #include<iostream> #include<cstdio&g ...
- LOJ 2551 「JSOI2018」列队——主席树+二分
题目:https://loj.ac/problem/2551 答案是排序后依次走到 K ~ K+r-l . 想维护一个区间排序后的结果,使得可以在上面二分.求和:二分可以知道贡献是正还是负. 于是想用 ...
随机推荐
- openstack ocata版(脚本)计算节点安装
一.初始化环境: 1.安装软件包: yum -y install centos-release-openstack-ocata yum -y upgrade yum -y install python ...
- Linux Shell编程 awk命令
概述 awk是一种编程语言,用于在linux/unix下对文本和数据进行处理.数据可以来自标准输入(stdin).一个或多个文件,或其它命令的输出.它支持用户自定义函数和动态正则表达式等先进功能,是l ...
- $.proxy() 的妙用
$.proxy() 最主要就是用来修改函数执行时的上下文对象的. 先看以下情景: <div id="panel" style="display:none;" ...
- linux kernel内存回收机制
转:http://www.wowotech.net/linux_kenrel/233.html linux kernel内存回收机制 作者:itrocker 发布于:2015-11-12 20:37 ...
- PHP验证是否为图片格式文件
/** * 判断是否为图片格式(jpg/jpeg/gif/png)文件 * * @param string $filePath * @return bool|string */ function is ...
- 大话设计模式之PHP篇 - 适配器模式
定义将一个类的接口转换成客户希望的另外一个接口,使用原本不兼容的而不能在一起工作的那些类可以在一起工作. 角色Target适配目标,该角色定义把其他类转换为何种接口,也就是我们的期望接口.Adapte ...
- Ubuntu: 无法使用su命令
Ubuntu 无法使用su命令解决方案 在Ubuntu上编译Qt环境时发现无法使用su命令切换到root用户,通过网上查找发现解决方案如下: xt@xt-ubuntu:~$ su密码: su:认证失败 ...
- codeforces 155D 质数
题意:有编号1到n的n台机器,有m次操作,操作为开启或关闭机器,成功开启机器k的条件为k和所有已经开启的机器编号互质. 思路:vis[i]数组存放占领i这个位置的机器编号,因为所有开启的机器的编号互质 ...
- 算法总结之 将单链表的每K个节点之间逆序
给定一个单链表的表头节点head,实现一个调整单链表的函数,是的每k个节点之间逆序,如果最后不够k个节点一组,则不调整最后几个节点 思路: 如果k的值小于2,不调整.k<1 没有意义,k==1代 ...
- 操作文件和目录【TLCL】
cp – Copy files and directories mv – Move/rename files and directories mkdir – Create directories rm ...