题面传送门

题意:

给定 \(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)\)

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
template<typename T> void read(T &x){
char c=getchar();T neg=1;
while(!isdigit(c)){if(c=='-') neg=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=neg;
}
const int MAXN=1e5;
const int MAXK=10;
const int MOD=1e9+7;
int n,m;pii p[MAXN+5];
struct segtree{
struct node{
int l,r,val,lz;
} s[MAXN*8+5];
void build(int k,int l,int r){
s[k].l=l;s[k].r=r;s[k].lz=1;if(l==r) return;
int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}
void update(int k){s[k].val=(s[k<<1].val+s[k<<1|1].val)%MOD;}
void pushdown(int k){
if(s[k].lz!=1){
s[k<<1].val=1ll*s[k<<1].val*s[k].lz%MOD;
s[k<<1|1].val=1ll*s[k<<1|1].val*s[k].lz%MOD;
s[k<<1].lz=1ll*s[k<<1].lz*s[k].lz%MOD;
s[k<<1|1].lz=1ll*s[k<<1|1].lz*s[k].lz%MOD;
s[k].lz=1;
}
}
void mul(int k,int l,int r,int x){
if(l>r) return;
if(l<=s[k].l&&s[k].r<=r){
s[k].val=2ll*s[k].val%MOD;
s[k].lz=2ll*s[k].lz%MOD;return;
} pushdown(k);int mid=(s[k].l+s[k].r)>>1;
if(r<=mid) mul(k<<1,l,r,x);
else if(l>mid) mul(k<<1|1,l,r,x);
else mul(k<<1,l,mid,x),mul(k<<1|1,mid+1,r,x);
update(k);
}
void add(int k,int p,int x){
if(s[k].l==s[k].r){s[k].val=(s[k].val+x)%MOD;return;}
pushdown(k);int mid=(s[k].l+s[k].r)>>1;
if(p<=mid) add(k<<1,p,x);else add(k<<1|1,p,x);
update(k);
}
int query(int k,int l,int r){
if(l>r) return 0;if(l<=s[k].l&&s[k].r<=r) return s[k].val;
pushdown(k);int mid=(s[k].l+s[k].r)>>1;
if(r<=mid) return query(k<<1,l,r);else if(l>mid) return query(k<<1|1,l,r);
else return (query(k<<1,l,mid)+query(k<<1|1,mid+1,r))%MOD;
}
} t[MAXK+2];
int x[MAXK+2];
int c[MAXK+2][MAXK+2];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d%d",&p[i].fi,&p[i].se);
for(int i=0;i<=MAXK;i++){
c[i][0]=1;for(int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1];
}
sort(p+1,p+n+1);
for(int i=0;i<=m;i++) t[i].build(1,0,2*n);
t[0].add(1,0,1);
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
int val=t[j].query(1,p[i].fi,p[i].se);
t[j].add(1,p[i].se,val);//condition 2
}
for(int j=0;j<=m;j++) x[j]=t[j].query(1,0,p[i].fi-1);
for(int j=0;j<=m;j++){
int val=0;
for(int k=0;k<=j;k++) val=(val+1ll*x[k]*c[j][k]%MOD)%MOD;
t[j].add(1,p[i].se,val);//condition 1
}
for(int j=0;j<=m;j++) t[j].mul(1,p[i].se+1,2*n,2);//condition 3
}
printf("%d\n",t[m].query(1,0,2*n));
return 0;
}

洛谷 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. 使用vue-cli+webpack搭建vue开发环境

    在这里我真的很开心,好久没有用过博客,今天突然看到了我的博客有不少人看过,虽然没有留下脚印,但是还是激起了我重新拿起博客的信心,感谢大家. 在这里我们需要首先下载node,因为我们要用到npm包下载, ...

  2. SharkCTF2021 The_nature_of_the_human

    (信安数基的quiz1写不出来 来这放题解泄愤) crypto类题. 题面 其加密的大致过程是,对明文flag中的逐个字符,随机使用三种加密方式: 第一种,对该字符进行sha256加密后以16进制形式 ...

  3. RabbitMQ:从入门到搞定面试官

    安装 使用docker安装,注意要安装tag后缀为management的镜像(包含web管理插件),我这里使用的是rabbitmq:3.8-management 1. 拉取镜像 shell docke ...

  4. 第七次Scrum Metting

    日期:2021年5月5日 会议主要内容概述:前后端对接,以及接下来的测试优化等工作. 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 徐宇龙 后端 测试数据模块和 ...

  5. 基于JWT的Token身份验证

    ​ 身份验证,是指通过一定的手段,完成对用户身份的确认.为了及时的识别发送请求的用户身份,我们调研了常见的几种认证方式,cookie.session和token. 1.Cookie ​ cookie是 ...

  6. python的random模块生成随机数

    python的random函数 random.random() 生成0-1之间的随机数 random.uniform(a,b)生成a,b之间的浮点数 random.randint(a,b)生成a,b之 ...

  7. UVM RAL模型和内置seq

    转载:UVM RAL模型:用法和应用_寄存器 (sohu.com) 在系统设计中通常会面临两大挑战:缩小技术节点的规模和上市时间(TTM,Time to Market).为了适应激烈的市场竞争,大多数 ...

  8. [转]DDR内存条rank的概念和区分

    1:什么是RANK? 答:CPU与内存之间的接口位宽是64bit,也就意味着CPU在一个时钟周期内会向内存发送或从内存读取64bit的数据.可是,单个内存颗粒的位宽仅有4bit.8bit或16bit, ...

  9. 第35篇-方法调用指令之invokespecial与invokestatic

    这一篇将详细介绍invokespecial和invokestatic字节码指令的汇编实现逻辑 1.invokespecial指令 invokespecial指令的模板定义如下: def(Bytecod ...

  10. redis的一般使用和常规配置

    https://www.cnblogs.com/HTLucky/p/12027889.html Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANS ...