题面传送门 题意: 给定 \(n\) 条线段,第 \(i\) 条线段左右端点分别为 \(l_i,r_i\) 定义一个线段集合的复杂度为其形成的连通块的个数的 \(k\) 次方. 求这 \(n\) 条线段所有子集的复杂度之和. 答案对 \(10^9+7\) 取模. \(1\leq n\leq 10^5\),\(1\leq k\leq 10\) 将所有线段按左端点从小到大排序,然后依次加入这 \(n\) 个线段. 先考虑 \(k=1\) 的情形,定义 \(f_r\) 为当前右端点最大的线段的右端点为…
To 洛谷.2982 慢下来Slowing down 题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows conveniently numbered 1..N move from the barn to her private pasture. The pastures are organized as a tree, with the barn being on pasture 1. Exactly N-1 cow…
题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内,那就把它用并查集并起来.最后对于一个询问,直接用并查集找就好了. 但是因为有撤销操作,所以在并查集合并的时候,我们将需要合并的两个点放进栈中,最后栈序撤销,所以只能考虑按秩合并而不能路径压缩. #include <map> #include <vector> #include <…
二分mid,然后用1~mid的操作在差分序列上加减,最后把差分序列前缀和起来,看是否有有超过初始r值的 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e6,INF=1e9; long long n,m,a[N],d[N],x[N],y[N],s[N]; int read() { int r=…
题目: 洛谷4219 分析: 很明显,查询的是删掉某条边后两端点所在连通块大小的乘积. 有加边和删边,想到LCT.但是我不会用LCT查连通块大小啊.果断弃了 有加边和删边,还跟连通性有关,于是开始yy线段树分治做法(不知道线段树分治?推荐一个伪模板题BZOJ4025二分图事实上这个链接是指向我的博客的).把每次操作(加边或查询)看做一个时刻,一条边存在的区间就是它加入后没有被查询的时间区间的并.于是用可撤销并查集维护一下连通块大小即可. 代码: #include <cstdio> #inclu…
题意 题目链接 Sol 首先不难想到一个dp,设\(f[i][j]\)表示\(i\)的子树内选择的最小值至少为\(j\)的最大个数 转移的时候维护一个后缀\(mx\)然后直接加 因为后缀max是单调不升的,那么我们可以维护他的差分数组(两个差分数组相加再求和 与 对两个原数组直接求和是一样的) 向上合并的过程中对\(a[x]\)处\(+1\),再找到\(a[x]\)之前为\(1\)的位置\(-1\)即可 (怎么感觉暴力区间加也可以qwq) 复杂度\(O(nlogn)\) // luogu-jud…
题意 题目链接 Sol 说一个后缀自动机+线段树的无脑做法 首先建出SAM,然后对parent树进行dp,维护最大次大值,最小次小值 显然一个串能更新答案的区间是\([len_{fa_{x}} + 1, len_x]\),方案数就相当于是从\(siz_x\)里面选两个,也就是\(\frac{siz_x (siz_x - 1)}{2}\) 直接拿线段树维护一下,标记永久化一下炒鸡好写~ #include<bits/stdc++.h> #define int long long #define L…
题目链接 下落一个d*s的方块,则要在这个平面区域找一个最高的h' 更新整个平面区域的值为h+h' 对于本题,维护最大高度h和all 对于平面的x轴维护一棵线段树t1,每个t1的节点维护对应y轴的两棵线段树t2(h和all) (同一维,需要维护独立的两棵线段树) t1要用标记永久化实现,t2普通和标记永久化都可以 空间O(n^2) 时间O(n*(logn)^2) 标记永久化: 对于树套树(二维线段树)来说,标记下传(PushDown)与信息上传(PushUp)就很难实现了 这时用到标记永久化 写…
题意 题目链接 Sol 显然整个序列的形态对询问没什么影响 设权值\(>=s\)的有\(k\)个. 我们可以让这些数每次都被选择 那么剩下的数,假设值为\(a_i\)次,则可以\(a_i\)次被选择 一个显然的思路是每次选最大的C个 那么只需要判断\(\sum a_i >=(c - k)*s\)即可 权值线段树维护一下 #include<bits/stdc++.h> #define Pair pair<int, int> #define MP(x, y) make_pa…
传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 using namespace std; inline int read(){ int ans=0; char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))ans=(ans<<3)+(ans<<1)…