主席树

hdu5919 Sequence Il 主席树

一个人想着一个人 提交于 2019-12-11 20:01:58
题目链接 题意 给出一个序列,问区间[l, r]中所有不同元素出现的第一个位置(取最左)组成的序列中的第k/2个,k是区间不同数的个数。 第i个询问区间依赖于第i-1个询问的答案,所以是强制在线的。 思路 区间第k个,显然是主席树,和查询区间不同数的个数一样,都是相同的数只取一个,但这个是取相同数的最前面一个,所以在建树的时候倒过来建就可以满足要求,然后要查询位置第k/2的数的位置,所以先求出这个区间[l,r]内不同数的个数,然后直接询问区间第k/2就可以。 # include <bits/stdc++.h> using namespace std ; const int maxn = 2e5 + 7 ; typedef long long ll ; int n , m , root [ maxn ] , cnt ; struct node { int l , r , sum ; } T [ maxn * 40 ] ; void update ( int l , int r , int & x , int y , int pos , int C ) { T [ ++ cnt ] = T [ y ] ; T [ cnt ] . sum + = C ; x = cnt ; if ( l == r ) return ; int mid = ( l + r ) >> 1 ; if (

[[FJOI2016]神秘数][主席树]

陌路散爱 提交于 2019-12-07 11:37:40
明白之后 5min 就写好了…自闭… 这题的题意是问你 \([L,R]\) 区间的数字不能构成的数字的最小值… 首先考虑 如果 \([1,x]\) 可以被表示 那么加入一个 \(a_i\) 显然 \([1,x+a_i]\) 都可以被表示 有什么好办法呢 当然有 \(O(q * \sum_{i\in[L,R]}{a_i}*[R-L+1])\) ( 雾 ) 区间求和问题啥的考虑主席树,首先我不会证明复杂度,是因为我菜/kk 还是一样的套路 讨论 \([1,x]\) 对于区间求 \(\sum_{i\in[L,R]}[a_i<=ans]\) \([ans\) 初值是1 \(]\) 显然此时 \([1,ans-1]\) 都可以表示出来 所以考虑扩大区间使得这个 \(res = \sum_{i\in[L,R]}[a_i<=ans]\) 如果值比 \(ans\) 小肯定是不可以构成 \(ans+1\) 的 所以无需扩展… #include<bits/stdc++.h> using ll = long long ; using namespace std ; int read() { int x = 0 , f = 1 ; char c = getchar() ; while(c < '0' || c > '9') { if(c == '-') f = -1 ; c = getchar() ; }

Optimal Subsequences(主席树)

╄→尐↘猪︶ㄣ 提交于 2019-12-05 23:21:51
题意: 给定一个序列,长度为n(<=2e5),有m(<=2e5)个询问,每个询问包含k和pos,要从原序列中选出一个长度为k的子序列,要求是这个序列的和是所有长度为k的序列中最大的,且是字典序最小的,要求输出子序列中第pos个元素。 思路: 显然要是长度为k的序列中和最大,必须要优先选大的数。显然必须全部选的数不需要考虑位置,部分选的数(必定是最小的数)肯定优先选择坐标小的,因此可以将所有数按数值从大到小排,然后坐标从小到达排,前k的数就是每次要选的数。而第pos个元素就是排好的数前k个中坐标值第pos小的,用主席树维护坐标值就好了。 #include <bits/stdc++.h> using namespace std; const int maxn=2e5+5; const int Log=40; int num[maxn*Log],lson[maxn*Log],rson[maxn*Log]; int root[maxn]; int tot; int build(int l,int r){ int pos=++tot; if(l<r){ int mid=(l+r)>>1; lson[pos]=build(l,mid); rson[pos]=build(mid+1,r); } return pos; } int update(int rt,int l,int r,int p){

浅谈主席树

旧时模样 提交于 2019-12-05 11:42:05
浅谈主席树 主席树,又名可持久化线段树,函数式线段树 (我也不知道啥意思) 。之所以叫主席树是因为发明人黄嘉泰姓名缩写是hjt (知道是谁吧) 首先,可持久化线段树,顾名思义 它是持久的 ,它支持询问过去版本,也就是说在过去某一次操作时的树,那么这怎么实现呢? 例题1: 给你一个长度为 \(n\) 的数组 \(a_1,a_2,...,a_n\) ,现在有 \(m\) 次操作: 1.将 \(a_i\) 变为 \(x\) 2.询问在第k次操作后, \(\Sigma_{i=l}^r a_i\) 的值 样例输入 4 1000 200 30 4 5 1 3 50 1 2 600 2 0 1 4 2 1 1 4 2 2 1 4 样例输出 1234 1254 1654 和以往不同,现在询问是对某一次的操作后的序列做询问。 如果用线段树维护区间和,那我们需要存下每次修改完后的线段树。 一个线段树需要 O(n) 的空间,显然不能存下 n 颗线段树,但是我们可以从这里找找突破口。 不妨先考虑最基本的线段树 第一次操作:把第 3 个位置改为 50 可以发现的是,这颗线段树和上一颗线段树只有 \(logn\) 个节点发生了变化。 第二次操作:把第 2 个位置改为 600 可以发现的是,这颗线段树和上一颗线段树同样也只有 \(logn\) 个节点发生了变化 我们发现,每一次单点修改,发生改变的节点只有 \

P3293 [SCOI2016]美味 主席树+按位贪心

牧云@^-^@ 提交于 2019-12-05 09:50:08
给定长度为 \(n\) 序列 \(a[i]\) ,每次询问区间 \([l,r]\) ,并给定 \(b,x\) 中的一个数 \(p=a[i]\) ,使得最大化 \(b \bigoplus p^x\) 主席树+按位贪心。 我们可以直接贪每一位长什么样子,然后再主席树上区间查询即可。 #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #define R register int using namespace std; namespace Luitaryi { inline int g() { R x=0,f=1; register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f; do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f; } const int N=200010,B=17; int n,m,L,tot,a[N]; int sum[N*20],ls[N*20],rs[N*20],rt[N]; inline void ins(int& tr,int t,int l,int r,int p) { tr=++tot; sum[tr]

奇技淫巧

巧了我就是萌 提交于 2019-12-03 17:34:52
一、点权转边权:建一个超级源点,连接每个节点,边权为该点的点权,跑一边最短路就可以求出点权加路径长的最小值了。 二、用带权并查集来判断m个操作是否正确:若 \(l-1\) 与 \(r\) 是否在一个并查集里,若不在,就合并;若在,就判断是否满足条件。 三、 \(x\bigoplus x=0,0\bigoplus x=x\) 四、贪心策略假如不正确,先考虑是否可以反悔。 五、求区间内的互异个数:1.带修改:树套树或带修莫队(看数据范围);2.不带修改:主席树(在线, \(O(n\log n)\) ),莫队(离线, \(O(n \sqrt n)\) ) 六、求区间第k大:树套树或主席树 七、求区间异或信息:可持久化0-1Trie树或线性基 八、维护区间信息时,假如不会,可以用分块敲个部分分 来源: https://www.cnblogs.com/nth-element/p/11805126.html

主席树

戏子无情 提交于 2019-12-03 10:06:45
主席树是 以前缀和形式基于 权值线段树 建立的可持久化线段树,可持久化指的是它保存了这棵树的所有历史版本. 最简单的办法是:如果你输入了n个数,那么每输入一个数字a[i],就构造一棵保存了从a[1]到a[i]的权值线段树,由于只增加了log n 的节点数,我们增加改变的节点并将没有改变的子树指向该节点,这样需要的空间开销只有n*(4+logn) 我们可以把第j棵树和第(i-1)棵树上的每个点的权值相减,来得到一棵新的权值线段树,而这个新的权值线段树相当于是输入了a[i]到a[j]以后得到的。 模板题 K-th Number 后面将第 k小/大 说成kth 解决什么问题: 给定一段区间,静态求区间kth 想想方法: 暴力:对于每一个询问,排个序,就行了,时间复杂度O(nmlogn) 莫队+树状数组:树状数组可以求给定区间kth kthkth,使用二分+树状数组,具体不展开,但是多个区间的话,需要不断地进行树状数组的add/del操作,那么使用莫队来优化区间端点的移动问题,时间复杂度O((n+m)√n logn) 莫队复杂度*树状数组复杂度 莫队+平衡树:把树状数组的部分替换成二叉查找树,用splay的一部分操作,需要用到kth操作,不用翻转标记什么的,时间复杂度O((n+m)√n logn)跟上面的一样 目前想想,也就这三种方法,各有优劣,暴力时间复杂度不行,但是可以在线

主席树笔记

馋奶兔 提交于 2019-12-03 04:04:30
主席树笔记 By BigYellowDog 前置芝士:线段树、前缀和、最好还有平衡树。 导入 主席树是什么?它可以干嘛?为什么要用它? 主席树这个名字跟其功能没有关系。名字来源据说是hjt大牛发明的,根据其网名命名的。 主席树真正的名字叫可持久化线段树。 假设现在有这么一个问题:现有一个序列,q次询问。每次问区间[l, r]里的最大值。 很简单啊,线段树 / st表就好。 那改一下,每次询问区间[l, r]里的次大值。 很简单啊,线段树就好,只不过多维护一个值而已。 那再改一下,每次询问区间[l, r]里的第k大值。 ... ... emmm反正我是写不出来了。 那么主席树就是解决求区间第k大此类问题的。 当然,区间第k大还可以用整体二分。但主席树易理解,码量也不大。所以是一种性价比很高的算法。 原理 现在有一个序列3 5 4 1 2,请找出区间[1, 4]的第2大。 ok现在来模拟主席树算法过程。 建出一个空树(树0),如下图。 棕色数字表示节点的值。 (1~5)这个节点表示1 <= 值 <= 5的个数 (1~3)这个节点表示1 <= 值 <= 3的个数 ... ...注意这个一颗权值线段树。点的左右端点表示权值的边界。 插入序列中第一个数3,图就变成了(树1) 插入序列中第二个数5,图就变成了(树2) 一直插完序列中第4个数1后,图就变成了(树4) 到这里打住

HDU - 5788 Level Up 主席树 + 树状数组

匿名 (未验证) 提交于 2019-12-02 23:59:01
HDU - 5788 我们考虑把每个点遍历一遍, 把枚举的当前的这个点改成100000对答案的影响。 如果我们把 u 变成 100000, 受到影响的是 u 以及它的祖先, 我们记midu为子树u的中位数, nexmidu为子树u中位数的下一个数。 只有 a[ u ]的值小于等于祖先的mid, 才会改变祖先的薪水, 变成nexmidu。 所以我们用主席树求出每个子树的mid 和 nexmid。 然后dfs一遍整棵树, 用树状数组去更新答案。 #pragma GCC optimize ( 2 ) #pragma GCC optimize ( 3 ) #include < bits / stdc ++. h > #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair < LL , LL > #define PLI pair < LL , int > #define PII pair < int , int > #define SZ ( x ) (( int ) x . size ()) #define ALL ( x ) ( x ). begin (

2019ICPC南京网络赛总结

匿名 (未验证) 提交于 2019-12-02 23:57:01
这次是在学校打的,总体不算好,过两题校排200多..很惨. 开场一段时间没人过题,但是很多人交I, 我也就再看,看着看着发现不可做,这时候转F,花了半天读懂题意的时候想到主席树查找.但是主席树这种查找第一次写,写的很慢,而且写好了之后交上去Tle.同时也快两个小时.队友说H可写.过得也多.讨论了下就是两点最短路. 跑了SPFA,T了.这时候我不确定是不是SPFA.就又推了一边图,然后改代码发现是vector清零的问题..因为这个图是0开始..平常都是1开始..过了H之后就开始了F的噩梦.数组开大了之后来了一发PE,改了一下又RE..因为不知道计蒜客的判题.搞来搞去交了好多发RE.最后找着找着发现主席树的节点标记忘记重置了...真的低级错误..改了一下就过了..最后剩的时间也不多.A题也就想了个大概. 赛后F是set维护二分找..当时有想过滑窗法, 但是没有想到二分,不然set会好写很多.也不会出现这种bug. 希望后面几场不会出现这种问题了. 来源:博客园 作者: YDDDD 链接:https://www.cnblogs.com/YDDDD/p/11444381.html