P4559 [JSOI2018]列队 主席树

  题意: 有n个人 每个人有其一开始所在的位置   有m个询问   l r k    问编号为l到r的人填满区间 k----k+r-l  需要的最少距离

很容易发现按照原来的相对位置来填k开始的位置肯定是一种最优解

lr的编号区间很容易想到主席树

所以问题转化为如何优化主席树的询问

1、如果遍历每个人 然后累和每个人的距离 肯定会超时  复杂度接近on

2、可以分三种情况讨论

  如果所有的人都在   应到位置的左边  那么贡献为

  如果所有的人都在    应到位置的右边 那么贡献为 

  否则的话递归到子树继续进行分类

学会了主席树一种新的查询方式!!!

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<‘=‘<<(x)<<endl)
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
typedef pair<int,int>pii;
//////////////////////////////////
const int N=1e6+10;
int T[N],lson[N<<5],rson[N<<5],ncnt,n,m;
ll t[N<<5],sum[N<<5];
void upnode(int x,int l,int r,int pre,int &pos)
{
    pos=++ncnt;
    lson[pos]=lson[pre];rson[pos]=rson[pre];
    t[pos]=t[pre]+1;
    sum[pos]=sum[pre]+x;
    int m=(l+r)>>1;
    if(l==r)return ;
    if(x<=m)upnode(x,l,m,lson[pre],lson[pos]);
    else upnode(x,m+1,r,rson[pre],rson[pos]);
}
ll qsum(int L,int R,int l,int r,int pre,int pos)
{
    if(L>R)return 0;
    if(r<=L)return 1ll*(L+R)*(R-L+1)/2-(sum[pos]-sum[pre]);
    if(l>=R)return  (sum[pos]-sum[pre])-1ll*(L+R)*(R-L+1)/2;
    if(l==r)return 0;int m=(l+r)>>1;
    int peo=t[lson[pos]]-t[lson[pre]];
    return qsum(L,L+peo-1,l,m,lson[pre],lson[pos])+qsum(L+peo,R,m+1,r,rson[pre],rson[pos]);
}
int main()
{
    scanf("%d%d",&n,&m);int x;
    rep(i,1,n)scanf("%d",&x),upnode(x,1,1e6,T[i-1],T[i]);
    int l,r,k;
    while(m--)
    {
        scanf("%d%d%d",&l,&r,&k);
        printf("%lld\n",qsum(k,k+r-l,1,1e6,T[l-1],T[r]));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/bxd123/p/11562975.html

时间: 2024-08-11 11:45:22

P4559 [JSOI2018]列队 主席树的相关文章

P4559 [JSOI2018]列队

\(\color{#0066ff}{ 题目描述 }\) 作为一名大学生,九条可怜在去年参加了她人生中的最后一次军训. 军训中的一个重要项目是练习列队,为了训练学生,教官给每一个学生分配了一个休息位置.每次训练开始前,所有学生都在各自的休息位置休息,但是当教官发出集合命令后,被点到的学生必须要到指定位置集合. 为了简化问题,我们把休息位置和集合位置抽象成一根数轴.一共有 \(n\) 个学生,第 \(i\) 个学生的休息位置是 \(a_i\).每一次命令,教官会指定一个区间 \([l,r]\) 和集

[JSOI2018]列队

题解 好像是\(JSOI2018\)最简单的一道题了,但是我还是做了好久== 所有人都往一个区间走可以转化为把编号为\([l,r]\)的人按照开始位置排序,然后排名为i的人走到\(k+i-1\)的位置的花费和 这样就是\(O(nmlogn)\)的了 那考虑用数据结构来优化这个过程 首先想到能不能用所有人的位置和-\((k+k+r-l+1)*(r-l+1)/2\) 显然不能,因为有些人会往左走,有些人会往右走 但我们可以发现在\([l,r]\)中一定有一个分界点,使得这个分界点往左的人都往右走,这

[poj2104]可持久化线段树入门题(主席树)

解题关键:离线求区间第k小,主席树的经典裸题: 对主席树的理解:主席树维护的是一段序列中某个数字出现的次数,所以需要预先离散化,最好使用vector的erase和unique函数,很方便:如果求整段序列的第k小,我们会想到离散化二分和线段树的做法, 而主席树只是保存了序列的前缀和,排序之后,对序列的前缀分别做线段树,具有差分的性质,因此可以求任意区间的第k小,如果主席树维护索引,只需要求出某个数字在主席树中的位置,即为sort之后v中的索引:若要求第k大,建树时反向排序即可 1 #include

【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树

这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,Lca只是他的一种应用,他可以搞各种树上问题,树上倍增一般都会用到f数组. |||.我们跑出来dfs序就能在他的上面进行主席树了. IV.别忘了离散. V.他可能不连通,我一开始想到了,但是我觉得出题人可能会是好(S)人(B),但是...... #include <cstdio> #include

[bzoj3932][CQOI2015]任务查询系统-题解[主席树][权值线段树]

Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行 ),其优先级为Pi.同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同.调度系统会经常向 查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个 )的优先级之和是多少.特别的,如

BZOJ_3207_花神的嘲讽计划1_(Hash+主席树)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3207 给出一个长度为\(n\)的串,以及\(m\)个长度为\(k\)的串,求每个长度为\(k\)的串在原串\([x,y]\)区间是否出现过. 分析 这道题要求对比长度为\(k\)的串,于是我们把这些串的Hash值都算出来,问题就转化成了求\([x,y]\)的区间中是否出现过某Hash值. 求区间中某一个值出现了多少次,可以用主席树. p.s. 1.学习了主席树指针的写法,比数组慢好多啊...

[主席树]ZOJ3888 Twelves Monkeys

题意:有n年,其中m年可以乘时光机回到过去,q个询问 下面m行,x,y 表示可以在y年穿越回x年, 保证y>x 下面q个询问, 每个询问有个年份k 问的是k年前面 有多少年可以通过一种以上($\ge 2$)方法穿越回去的, 其中时光机只能用一次 比如案例 9 3 3 9 1 6 1 4 1 6 7 2 如图 对于询问 6这一年:1.穿越回第1年  2.等时间过呀过呀过到第9年,再穿越回第1年 那么第1年就有两种方法可以穿越回去, 同理, 2.3.4年也有同样两种方法(回到1再等时间过呀过 过到2

POJ2104主席树模板题

完成新成就——B站上看了算法https://www.bilibili.com/video/av4619406/?from=search&seid=17909472848554781180#page=2 K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 60158   Accepted: 21054 Case Time Limit: 2000MS Description You are working

【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成.每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络.该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信. 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略.但是由于路由器老化,在这些