CF484E Sign on Fence #include<bits/stdc++.h> #define RG register #define IL inline #define _ 100100 #define inf 1e9+7 using namespace std; IL int gi(){ RG int data = 0 , m = 1; RG char ch = 0; while(ch != '-' && (ch<'0' || ch > '9')) c…
[国家集训队]middle 主席树的想法感觉挺妙的,但是这题数据范围这么小,直接分块草过去不就好了吗 二分是要二分的,把\(<x\)置\(-1\),\(\ge x\)的置\(1\),于是我们需要取一个\(\ge 0\)的区间 对询问\(a,b,c,d\),其中\([b,c]\)是必选的,\([a,b-1]\)取后缀最大和,\([c+1,d]\)取前缀最大和 我们直接分块,对每个块的每个答案\(x\)维护一个块内和,前缀最大和和后缀最大和就可以了 然后询问的时候暴力跳块就好了 复杂度\(O(n\s…
[国家集训队]middle 题目 解法 开\(n\)颗线段树,将第\(i\)颗线段树中大于等于第\(i\)小的数权值赋为1,其他的则为-1,对于每个区间维护一个区间和,最大前缀和,最大后缀和. 然后二分答案,查询二分到的答案对应线段树. \(设s=[a,b-1]的最大后缀和+[b,c]的区间和+[c+1,d]的最大前缀和\) 若\(s\geq 0\),则答案可能更大,否则答案必须变小,仔细想想为什么. 这样不断二分即可. 考虑到开不下那么多线段树,而若排序后相邻线段树维护的序列只有一个元素不同,…
P2839 [国家集训队]middle 好妙的题啊,,,, 首先二分一个答案k,把数列里>=k的数置为1,=0就是k>=中位数,<0就是k<中位数 数列的最大和很好求哇 左边的最大后缀+中间+右边的最大前缀 主席树搞搞 完事了 // It is made by XZZ #include<cstdio> #include<algorithm> #define il inline #define rg register #define vd void #defi…
[LG2839][国家集训队]middle 题面 洛谷 题解 按照求中位数的套路,我们二分答案\(mid\),将大于等于\(mid\)的数设为\(1\),否则为\(-1\). 若一个区间和大于等于\(0\),则答案可以更大,反之亦然. 对于这个题,我们只要维护出\([b+1,c-1]\)之间二分答案后的和,\([a,b]\)的最大右段和,\([c,d]\)的最大左段和,判断这三项加起来是否大于零即可. 我们维护这三项和的话,按照权值为前缀,建主席树就行了. 代码 #include <iostre…
题意 给定一个长度为n的数列,有m次询问,询问形如l r k 要你在区间[l,r]内选一个长度为k的区间,求区间最小数的最大值 Sol 二分答案 怎么判定,每种数字开一棵线段树 某个位置上的数大于等于它为1 那么就是求区间最大的1的序列长度大于k 二分的最优答案一定在这个区间内,否则不优 排序后就是用主席树优化空间 之前\(build\)一下,因为区间有长度不好赋值 # include <bits/stdc++.h> # define RG register # define IL inlin…
BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\((a,b,c,d)\),同样也可以二分中位数\(x\),然后把原序列对应地改为\(+1\)或\(-1\). 此时区间\([b,c]\)中的数是必选的,求一个和\(sum\).显然对于区间\([a,b-1]\),我们可以求一个和最大的后缀:对于区间\([c+1,d]\),可以求一个和最大的前缀.然后判断总和是…
题目链接:洛谷 题目大意:给定一个长度为$n$的序列,每次询问左端点在$[a,b]$,右端点在$[c,d]$的所有子区间的中位数的最大值.(强制在线) 这里的中位数定义为,对于一个长度为$n$的序列排序之后为$a_0,a_1,\ldots,a_{n-1}$,则$a_{\lfloor\frac{n}{2}\rfloor}$为这个序列的中位数. 数据范围:$1\leq n\leq 20000$,$1\leq q\leq 25000$,$1\leq a\leq b\leq c\leq d\leq n$…
题面 求中位数的套路:二分,大于等于的设为1,小于的设为-1 于是可以从小到大排序后依次加入可持久化线段树,这样每次只会变化一个位置 那左右端点是区间怎么办? 先把中间的算上,然后维护每个区间左右两侧最大子段和,左右和右左拼起来即可 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ,M=1e7+,inf=1e9; ],sum[M],lsum[M],rsum[M],qr…
题目大意:给你一个长度为$n$的序列$s$.$Q$个询问,问在$s$中的左端点在$[a,b]$之间,右端点在$[c,d]$之间的子段中,最大的中位数. 强制在线. 题解:区间中位数?二分答案,如果询问区间是给定的,对于每个询问,二分答案是多少,然后只要求出这个区间中有多少个数比二分的数大就行了,这就可以对每一个值建一棵主席树,把比它小的赋成$-1$,大于等于的赋成$1$,只需要区间和,就可以在$O(\log_2 n)$的时间判断一个解了. 但区间不给定.怎么办?注意到,$[b+1,c-1]$的值…