题面传送门

题意:

给定 \(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\) 为当前右端点最大的线段的右端点为 \(r\) 的所有集合的所形成的连通块之和。

当我们加入一条线段 \([l,r]\) 时,分三种情况:

  1. 对于右端点 \(\leq l-1\) 的集合,加入这条线段后复杂度会 \(+1\),右端点变为 \(r\),故将 \(f_1+1,f_2+1,\dots,f_{l-1}+1\)到 $ f_r$ 中。
  2. 对于右端点在 \(l\) 和 \(r\) 之间的集合,加入这条线段后复杂度不变,右端点变为 \(r\),故将 \(f_l,f_{l+1},\dots,f_r\) 累加到 \(f_r\) 中。
  3. 对于右端点 \(>r\) 的集合。加入这条线段后复杂度也不变,右端点也不变,故令所有 \(f_i(i>r)\) 乘 \(2\)。

最终答案即为所有 \(f_i\) 的和。

接下来考虑 \(k\) 不为 \(1\) 的情况。其实与 \(k=1\) 大差不差,只不过我们在情况 \(1\) 中,我们要支持维护 \((f_1+1)^k,(f_2+1)^k,\dots,(f_{l-1}+1)^k\) 的和。

这玩意儿可以用二项式定理展开为 \(\sum\limits_{i=1}^{l-1}\dbinom{k}{0}f_i^0+\dbinom{k}{1}f_i^1+\dbinom{k}{2}f_i^2+\dots+\dbinom{k}{k}f_i^k=\sum\limits_{j=0}^k\dbinom{k}{j}\sum\limits_{i=1}^{l-1}f_i^j\)。

建立 \(k+1\) 棵线段树,第 \(j\) 棵的下标 \(i\) 位置维护 \(f_i^j\),支持区间加,区间乘 \(2\),区间求和。

时间复杂度 \(\mathcal O(nk\log n)\)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define fi first
  4. #define se second
  5. #define fz(i,a,b) for(int i=a;i<=b;i++)
  6. #define fd(i,a,b) for(int i=a;i>=b;i--)
  7. #define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
  8. #define fill0(a) memset(a,0,sizeof(a))
  9. #define fill1(a) memset(a,-1,sizeof(a))
  10. #define fillbig(a) memset(a,63,sizeof(a))
  11. #define pb push_back
  12. #define ppb pop_back
  13. #define mp make_pair
  14. template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
  15. template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
  16. typedef pair<int,int> pii;
  17. typedef long long ll;
  18. template<typename T> void read(T &x){
  19. char c=getchar();T neg=1;
  20. while(!isdigit(c)){if(c=='-') neg=-1;c=getchar();}
  21. while(isdigit(c)) x=x*10+c-'0',c=getchar();
  22. x*=neg;
  23. }
  24. const int MAXN=1e5;
  25. const int MAXK=10;
  26. const int MOD=1e9+7;
  27. int n,m;pii p[MAXN+5];
  28. struct segtree{
  29. struct node{
  30. int l,r,val,lz;
  31. } s[MAXN*8+5];
  32. void build(int k,int l,int r){
  33. s[k].l=l;s[k].r=r;s[k].lz=1;if(l==r) return;
  34. int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
  35. }
  36. void update(int k){s[k].val=(s[k<<1].val+s[k<<1|1].val)%MOD;}
  37. void pushdown(int k){
  38. if(s[k].lz!=1){
  39. s[k<<1].val=1ll*s[k<<1].val*s[k].lz%MOD;
  40. s[k<<1|1].val=1ll*s[k<<1|1].val*s[k].lz%MOD;
  41. s[k<<1].lz=1ll*s[k<<1].lz*s[k].lz%MOD;
  42. s[k<<1|1].lz=1ll*s[k<<1|1].lz*s[k].lz%MOD;
  43. s[k].lz=1;
  44. }
  45. }
  46. void mul(int k,int l,int r,int x){
  47. if(l>r) return;
  48. if(l<=s[k].l&&s[k].r<=r){
  49. s[k].val=2ll*s[k].val%MOD;
  50. s[k].lz=2ll*s[k].lz%MOD;return;
  51. } pushdown(k);int mid=(s[k].l+s[k].r)>>1;
  52. if(r<=mid) mul(k<<1,l,r,x);
  53. else if(l>mid) mul(k<<1|1,l,r,x);
  54. else mul(k<<1,l,mid,x),mul(k<<1|1,mid+1,r,x);
  55. update(k);
  56. }
  57. void add(int k,int p,int x){
  58. if(s[k].l==s[k].r){s[k].val=(s[k].val+x)%MOD;return;}
  59. pushdown(k);int mid=(s[k].l+s[k].r)>>1;
  60. if(p<=mid) add(k<<1,p,x);else add(k<<1|1,p,x);
  61. update(k);
  62. }
  63. int query(int k,int l,int r){
  64. if(l>r) return 0;if(l<=s[k].l&&s[k].r<=r) return s[k].val;
  65. pushdown(k);int mid=(s[k].l+s[k].r)>>1;
  66. if(r<=mid) return query(k<<1,l,r);else if(l>mid) return query(k<<1|1,l,r);
  67. else return (query(k<<1,l,mid)+query(k<<1|1,mid+1,r))%MOD;
  68. }
  69. } t[MAXK+2];
  70. int x[MAXK+2];
  71. int c[MAXK+2][MAXK+2];
  72. int main(){
  73. scanf("%d%d",&n,&m);
  74. for(int i=1;i<=n;i++) scanf("%d%d",&p[i].fi,&p[i].se);
  75. for(int i=0;i<=MAXK;i++){
  76. c[i][0]=1;for(int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1];
  77. }
  78. sort(p+1,p+n+1);
  79. for(int i=0;i<=m;i++) t[i].build(1,0,2*n);
  80. t[0].add(1,0,1);
  81. for(int i=1;i<=n;i++){
  82. for(int j=0;j<=m;j++){
  83. int val=t[j].query(1,p[i].fi,p[i].se);
  84. t[j].add(1,p[i].se,val);//condition 2
  85. }
  86. for(int j=0;j<=m;j++) x[j]=t[j].query(1,0,p[i].fi-1);
  87. for(int j=0;j<=m;j++){
  88. int val=0;
  89. for(int k=0;k<=j;k++) val=(val+1ll*x[k]*c[j][k]%MOD)%MOD;
  90. t[j].add(1,p[i].se,val);//condition 1
  91. }
  92. for(int j=0;j<=m;j++) t[j].mul(1,p[i].se+1,2*n,2);//condition 3
  93. }
  94. printf("%d\n",t[m].query(1,0,2*n));
  95. return 0;
  96. }

洛谷 P6144 - [USACO20FEB]Help Yourself P(二项式定理+线段树)的更多相关文章

  1. 洛谷P2982 [USACO10FEB]慢下来Slowing down(线段树 DFS序 区间增减 单点查询)

    To 洛谷.2982 慢下来Slowing down 题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows con ...

  2. Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)

    题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...

  3. 洛谷 P1083 借教室【二分+差分/线段树】

    二分mid,然后用1~mid的操作在差分序列上加减,最后把差分序列前缀和起来,看是否有有超过初始r值的 #include<iostream> #include<cstdio> ...

  4. 【洛谷4219】[BJOI2014]大融合(线段树分治)

    题目: 洛谷4219 分析: 很明显,查询的是删掉某条边后两端点所在连通块大小的乘积. 有加边和删边,想到LCT.但是我不会用LCT查连通块大小啊.果断弃了 有加边和删边,还跟连通性有关,于是开始yy ...

  5. 洛谷P4577 [FJOI2018]领导集团问题(dp 线段树合并)

    题意 题目链接 Sol 首先不难想到一个dp,设\(f[i][j]\)表示\(i\)的子树内选择的最小值至少为\(j\)的最大个数 转移的时候维护一个后缀\(mx\)然后直接加 因为后缀max是单调不 ...

  6. 洛谷P2178 [NOI2015]品酒大会(后缀自动机 线段树)

    题意 题目链接 Sol 说一个后缀自动机+线段树的无脑做法 首先建出SAM,然后对parent树进行dp,维护最大次大值,最小次小值 显然一个串能更新答案的区间是\([len_{fa_{x}} + 1 ...

  7. 洛谷.3437.[POI2006]TET-Tetris 3D(二维线段树)

    题目链接 下落一个d*s的方块,则要在这个平面区域找一个最高的h' 更新整个平面区域的值为h+h' 对于本题,维护最大高度h和all 对于平面的x轴维护一棵线段树t1,每个t1的节点维护对应y轴的两棵 ...

  8. 洛谷P3586 [POI2015]LOG(贪心 权值线段树)

    题意 题目链接 Sol 显然整个序列的形态对询问没什么影响 设权值\(>=s\)的有\(k\)个. 我们可以让这些数每次都被选择 那么剩下的数,假设值为\(a_i\)次,则可以\(a_i\)次被 ...

  9. 2018.08.11 洛谷P3224 [HNOI2012]永无乡(线段树合并)

    传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 ...

随机推荐

  1. python的参数传递是值传递还是引用传递??

    函数参数传递机制,传值和引用的是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传递. 值传递(pa ...

  2. sql常用的统计公式

    hivesql中max,min函数不能作用于多列,因此在有上下门限区间限制时多用公式直接计算. max(x,y)=(x+y+ABS(x-y))/2 min(x,y)=(x+y-ABS(x-y))/2 ...

  3. python中常用的导包的方法和常用的库

    python中常用的导包的方法               导入包和包名的方法:1.import package.module 2.from package.module import  * 例一: ...

  4. Python 做简单的登录系统

    案例 之 登录系统原创作品1 该随笔 仅插入部分代码:全部py文件源代码请从百度网盘自行下载! 链接:https://pan.baidu.com/s/1_sTcDvs5XEGDcnpoQEIrMg 提 ...

  5. Linux信号处理编程

    01. 学习目标 了解信号中的基本概念 熟练使用信号相关的函数 了解内核中的阻塞信号集和未决信号集作用 熟悉信号集操作相关函数 熟练使用信号捕捉函数signal 熟练使用信号捕捉函数sigaction ...

  6. Hadoop MapReduce 保姆级吐血宝典,学习与面试必读此文!

    Hadoop 涉及的知识点如下图所示,本文将逐一讲解: 本文档参考了关于 Hadoop 的官网及其他众多资料整理而成,为了整洁的排版及舒适的阅读,对于模糊不清晰的图片及黑白图片进行重新绘制成了高清彩图 ...

  7. 【UE4 C++】绘制函数 Debug drawing functions

    基于UKismetSystemLibrary /** Draw a debug line */ UFUNCTION(BlueprintCallable, Category="Renderin ...

  8. 使用json-path解析json

    在我们的日常开发中,有时候需要从一个json字符串中获取一个值,或者从一段json字符串中获取到某些值,如果先使用Gson或Jackson转换成java对象在获取值,有些时候是很麻烦的,那么有没有一种 ...

  9. spring security实现简单的url权限拦截

    在一个系统中,权限的拦截是很常见的事情,通常情况下我们都是基于url进行拦截.那么在spring security中应该怎么配置呢. 大致步骤如下: 1.用户登录成功后我们需要拿到用户所拥有的权限,并 ...

  10. 深入理解Linux C语言内存管理

    问题不能拖,我这就来学习一下吧,争取一次搞定. 在任何程序设计环境及语言中,内存管理都十分重要. 内存管理的基本概念 分析C语言内存的分布先从Linux下可执行的C程序入手.现在有一个简单的C源程序h ...