bzoj 3653 谈笑风生——主席树】的更多相关文章

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3653 原来一直想怎么线段树合并.可是不会把角标挪一位. 查询的其实是子树内一段深度的点的 siz 和.因为是子树内,所以按 dfs 序建立主席树,角标是 dep ,值是 siz . 注意 long long .而且数组 *19 就会 RE ,*20就好了.不知为何. #include<iostream> #include<cstdio> #include<cstring…
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3653 对于一个 (a,b,c),分成 b 是 a 的祖先和 b 在 a 子树里两部分: 第一部分 b 可以选 min(dep[a]-1,k) 个,c 可以选 siz[a]-1 个,乘起来即可: 第二部分,要求 ∑siz[u]-1,其中 u 是 a 子树内到 a 距离不超过 k 的点: 考虑到子树在 dfs 序上就是一段区间,距离范围又可以看作 dep 范围,所以在 dfs 序上建主席树,就…
传送门 解题思路 首先对于一个\(a\)来说,要求\(b\)和\(c\),那么\(a,b,c\)一定在一条链上.把\(b\)分类讨论,如果\(b\)是\(a\)的祖宗,这个方案数就很好统计了,就是\(c\)在\(a\)的子树里随便选,产生的贡献为\((siz_a-1)*(min(k,dep_a))\).如果\(b\)是\(a\)的儿子,那么就考虑\(b\)作为每个点产生的贡献,发现为\(siz_x-1\),那么其实要求的就是\([dfn_a+1,dfn_a+siz_a-1]\)中深度为\([de…
题面:P3899 [湖南集训]谈笑风生 题解: 我很喜欢这道题. 因为A是给定的,所以实质是求二元组的个数.我们以A(即给定的P)作为基点寻找答案,那么情况分两类.一种是B为A的父亲,另一种是A为B的父亲. 第一种情况很好处理,写法见代码,懒得讲,反正很简单的. 第二种情况的话,按Dfs序建主席树,用主席树维护下标为Dep的序列,每次用Size-1(因为不能取本身:Size[i]即为以i为根的子树节点数)去更新, 询问的时候在以A为根的子树中查找Dep[A]+1~Dep[A]+K的和即可. 不思…
考虑b的两种情况,一种是p的祖先,这种点有min(k,de[p]-1)个,然后每个这种b都有si[p]-1个c点可选: 另一种是p的子孙,要求是在p的子树内且deep在de[p]+1~de[p]+k之间,然后一个这样的b点贡献是si[b]-1,也就是在他的子树内选c点,考虑怎么算这个,用dfs序维护,这样每次查p的子树就是一段区间了,然后用主席树按deep维护每个点的size-1,就可以直接查了 #include<iostream> #include<cstdio> using n…
BZOJ 洛谷 \(Description\) 给定一棵树,每次询问给定\(p,k\),求满足\(p,a\)都是\(b\)的祖先,且\(p,a\)距离不超过\(k\)的三元组\(p,a,b\)个数. \(n,q\leq3\times10^5\). \(Solution\) \(p,a,b\)都在一条链上. 那么如果\(a\)是\(p\)的祖先,答案就是\(\min(dep[p],\ k)*(sz[p]-1)\).可以\(O(1)\)计算. 如果\(a\)在\(p\)的子树中,答案就是\(\sum…
题意 给你一颗有 \(n\) 个点并且以 \(1\) 为根的树.共有 \(q\) 次询问,每次询问两个参数 \(p, k\) .询问有多少对点 \((p, a, b)\) 满足 \(p,a,b\) 为三个不同的点,\(p, a\) 都为 \(b\) 的祖先,且 \(p\) 到 \(a\) 的距离不能超过 \(k\) . \(n\le 300000 , q\le 300000\) 不要求强制在线. 题解 令 \(dep[u]\) 为点 \(u\) 的深度,\(sz[u]\) 为 \(u\) 的子树…
BZOJ 3524 Couriers 题意 求一个区间内出现超过区间长度的一半的数,如果没有则输出0. 题解 我可能太菜了吧--这道题愣是没想出来-- 维护权值主席树,记录每个数都出现过多少次: 查询的时候,这个数要么在较小的那一部分,要么在较大的那一部分:如果两部分的数的总数都不大于一开始那个"区间长度的一半",则不存在这样的数. #include <cstdio> #include <cmath> #include <cstring> #incl…
ORZ blutrex...... 主席树. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 1000500 #define maxq 1000500 #define maxe 1600500 using namespace std; struct edge { long long v,nxt; }e[maxe]; struct an…
主席树上树,对于每个节点,继承其父亲的,最后跑f[x]+f[y]-f[lca]-f[fa[lca]] 去重竟然要减一,我竟然不知道?? #include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #define N 100005 using namespace std; int e=1,head[N]; struct edge{…
2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2522  Solved: 1434[Submit][Status][Discuss] Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数. 其中a<b<c<d.位置也…
在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送.现在你要招募一批忍者,并把它们派遣给顾客.你需要为每个被派遣的忍者 支付一定的薪水,同时使得支付的薪水总额不超过你的预算.另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者…
https://www.lydsy.com/JudgeOnline/problem.php?id=3956 从描述可以得到性质: 每个好点对 ( 除了差值为1的好点对 ) 中间的数 ( i , j ) 一定有一个最大值, 视这个值控制这个好点对, 那么每个值最多只控制一个好点对. 然后我们就可以通过单调栈 ( 求出lp[i]左边第一个大于i的数的坐标, rp[i]右边第一个大于i的数的坐标, lf[i]左边第一个大于等于i的数的坐标 (为避免重复只统计有重复区间的值里的最左边一个,即lp=lf则…
题面:https://vjudge.net/problem/HYSBZ-2653 博客:https://blog.csdn.net/litble/article/details/78984846 这个题很明显不能建n棵动态开点的线段树,因为每颗线段树点分布都很密集,这样相当于都是满二叉树.但是,我们可以发现,相邻的每颗线段树只有一个位置不同,这样我们就可以用主席树了.主席树相当于每次只多开了O(logn)个节点就能新开一棵线段树. 代码: #include <bits/stdc++.h> #d…
2735: 世博会 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 124  Solved: 51[Submit][Status][Discuss] Description 四年一度的世博会又要举办了,Q国很荣幸成为了这次世博会的主办方.Q国主席QQ从全国各地收集了N件物品排成 一排,作为Q国馆的展出物.对于相邻摆放的一些物品,如果过于相似会让人觉得无聊,如果差别过大又会让人觉 得突兀.为了让人们对这次世博会的展出满意,QQ需要知道一些相邻物品的“…
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4571 区间找异或值最大,还带加法,可以用主席树: 可以按位考虑,然后通过加上之前已经有的答案.减去题目给的那个 x ,得到满足这一位最大的值的范围,查找一下有没有即可: 注意如果写 b&(1<<j) ,这个不仅是 0 或 1!所以用个 bool 类型存下来. 代码如下: #include<iostream> #include<cstdio> #includ…
题面 想了一个主席树做法 我们把每个区间的两个端点拆开 对$L,R$分别从小到大排序,分别从左到右依次把对应标号的$c_{i}$插入到权值主席树里 每次查询$p_{i}$,在排序后的$L,R$数组上分别二分找到第一个小于等于$p_{i}$的位置 那么$L,R$的主席树相减之后就是能对$p_{i}$产生贡献的区间 在主席树上二分即可 似乎平衡树和线段树的做法空间比我优秀得多.. #include <cstdio> #include <cstring> #include <alg…
题面 这道题应该比较裸吧. \(a\),\(b\)都是\(c\)的祖先. 那么第一种情况是\(b\)是\(a\)的祖先,那么方案数就是\(\min\{dep[a]-1,k\}\cdot (num[a]-1)\). 第二种是\(a\)是\(b\)的祖先,那么方案数是 \[ \sum_{c\in subtree(a),dep[c]-dep[a]\leq k} num[c]-1 \] 显然这东西用主席树,一个维度是dfs序,一个维度数深度维护一下就好了吧. #include<cstdio> #inc…
传送门 解题思路 首先可以想到一种暴力做法,就是询问时二分,然后大于等于这个值的设为1,否则设为-1,然后就和GSS1那样统计答案.但是发现这样时间空间复杂度都很爆炸,所以考虑预处理,可以用主席树来做了.以\(rt[i]\)为根线段树维护二分的答案为\(i\)的线段树,线段树下标是位置.处理的时候就排一遍序,然后每次\(mid+1\)的时候发现只有\(mid\)这个位置的值要变成\(-1\),所以可以直接处理. 代码 #include<iostream> #include<cstdio&…
#include<iostream> #include<string.h> #include<algorithm> #include<stdio.h> #include<math.h> #define rep(i,j,k) for(int i=j;i<=k;i++) #define per(i,j,k) for(int i=j;i>=k;i--) #define LL long long using namespace std; ;…
题面 传送门:https://www.luogu.org/problemnew/show/P3899 Solution 你们搞的这道题啊,excited! 这题真的很有意思. 首先,我们可以先理解一下题面:固定一个a,找到一个b,c就是a与b的公共子树中的某个点. 那么,我们显然可以把这个b分成两类,第一种是在a上面的,第二种在a下面的. 对于b在a上面的情况,显然,c一定是a的子树中的某个点,答案即为min(K,depth[a])*size[a] 对于b在a下面的情况,问题就会变得比较exci…
首先嘛,还是太弱了,想了好久QAQ 然后,这道题么,明显就是求sigma(size[x]) (x是y的儿子且层树小于k) 然后就可以发现:把前n个节点按深度建可持久化线段树,就能用前缀和维护了 其实不难打= = #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; #define maxn 300010 #define ma…
题目大意 在一棵单位边权的有根树上支持询问: 给定a,k求满足下列条件的有序三元对的个数. a,b,c互不相同 a,b均为c的祖先 a,b树上距离<=k 题解 solution 1 首先我们知道,c一定在以a为根的子树内,否则不满足条件2 对于一个询问a,k,我们知道b一定在a的k步以内 所以我们把问题分为两部分: b是a的祖先 a是b的祖先 对于问题一,我们容易发现答案即为\(min(dep_a,k)*(siz_a-1)\) 所以现在问题就在于我们如何处理问题2. 对于问题二我们在这里对c再进…
题目描述 设 T 为一棵有根树,我们做如下的定义: 设 a 和 b 为 T 中的两个不同节点.如果 a 是 b 的祖先,那么称 “ a 比 b 不知道高明到哪里去了 ” . 设 a 和 b 为 T 中的两个不同节点.如果 a 与 b 在树上的距离不超过某个给定常数 x ,那么称 “ a 与 b 谈笑风生 ” . 给定一棵 n 个节点的有根树 T ,节点的编号为 1-n ,根节点为 1 号节点.你需要回答 q 个询问,询问给定两个整数 p 和 k ,问有多少个有序三元组 (a,b,c) 满足:1.…
传送门 题意: 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数. 我会使用一些方式强制你在线. 最后一句话太可怕了$QAQ$ 首先需要知道怎么求中位数: 二分答案,$\ge$的为$1$,$<$的为$-1$,如果和$\ge 0$说明当前答案$\le$中位数 最大中位数?$GSS$! 只要求$[a,b].rm+(b,c)…
3585: mex Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 422[Submit][Status][Discuss] Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问l,r. Output 一行一个数,表示每个询问的答案. Sample Input 5 5 2 1…
Description 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称"a比b不知道 高明到哪里去了". ? 设a 和 b 为 T 中的两个不同节点.如果 a 与 b 在树上的距离不超过某个给定 常数x,那么称"a 与b 谈笑风生". 给定一棵n个节点的有根树T,节点的编号为1 到 n,根节点为1号节点.你需 要回答q 个询问,询问给定两个整数p和k,问有多少个有序三元组(a;b;c)满足: a.b和 c为 T…
https://www.lydsy.com/JudgeOnline/problem.php?id=2653 因为是两个方向向外延伸所以不能对编号取前缀和(这里只有前缀和向后传递的性质,不是实际意义的和),那么对排序后的数字取前缀和,线段树维护编号然后二分就可以了. 在一个值相对的线段树中,数小于该值的位置视为-1,数大于等于该值的位置视为+1. 那么当可取的区间内可以的到的最大的和>=0时该数就是合法的. 维护lmx, rmx, sum三个值分别表示该区间从左向右能得到的最大前缀和.从右向左能得…
题目: http://www.lydsy.com/JudgeOnline/problem.php?id=2653 题解: 设答案为ans,把大于等于ans的记为1,小于的记为-1,这样可以知道当前ans是大了还是小了 然后二分答案,就是求最大子段和的问题,根据网上的题解:[b,c]是必选的,然后选[a,b]和[c,d]的最大字段和就行了 #include<cstdio> #include<cstring> #include<algorithm> #define N 20…
思路: //By SiriusRen #include <bits/stdc++.h> using namespace std; ; ],fa[N],minn[N],rev[N],q[N],top,pre[N]; ],lson[N*],rson[N*],cnt,xx,yy,ans; struct Road{int x,y,wei;}road[N]; ]!=p&&ch[fa[p]][]!=p;} void push_up(int p){ minn[p]=p; ]]].wei<…