洛谷 P6144 - [USACO20FEB]Help Yourself P(二项式定理+线段树)
题意:
给定 \(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]\) 时,分三种情况:
- 对于右端点 \(\leq l-1\) 的集合,加入这条线段后复杂度会 \(+1\),右端点变为 \(r\),故将 \(f_1+1,f_2+1,\dots,f_{l-1}+1\)到 $ f_r$ 中。
- 对于右端点在 \(l\) 和 \(r\) 之间的集合,加入这条线段后复杂度不变,右端点变为 \(r\),故将 \(f_l,f_{l+1},\dots,f_r\) 累加到 \(f_r\) 中。
- 对于右端点 \(>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(二项式定理+线段树)的更多相关文章
- 洛谷P2982 [USACO10FEB]慢下来Slowing down(线段树 DFS序 区间增减 单点查询)
To 洛谷.2982 慢下来Slowing down 题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows con ...
- Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)
题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...
- 洛谷 P1083 借教室【二分+差分/线段树】
二分mid,然后用1~mid的操作在差分序列上加减,最后把差分序列前缀和起来,看是否有有超过初始r值的 #include<iostream> #include<cstdio> ...
- 【洛谷4219】[BJOI2014]大融合(线段树分治)
题目: 洛谷4219 分析: 很明显,查询的是删掉某条边后两端点所在连通块大小的乘积. 有加边和删边,想到LCT.但是我不会用LCT查连通块大小啊.果断弃了 有加边和删边,还跟连通性有关,于是开始yy ...
- 洛谷P4577 [FJOI2018]领导集团问题(dp 线段树合并)
题意 题目链接 Sol 首先不难想到一个dp,设\(f[i][j]\)表示\(i\)的子树内选择的最小值至少为\(j\)的最大个数 转移的时候维护一个后缀\(mx\)然后直接加 因为后缀max是单调不 ...
- 洛谷P2178 [NOI2015]品酒大会(后缀自动机 线段树)
题意 题目链接 Sol 说一个后缀自动机+线段树的无脑做法 首先建出SAM,然后对parent树进行dp,维护最大次大值,最小次小值 显然一个串能更新答案的区间是\([len_{fa_{x}} + 1 ...
- 洛谷.3437.[POI2006]TET-Tetris 3D(二维线段树)
题目链接 下落一个d*s的方块,则要在这个平面区域找一个最高的h' 更新整个平面区域的值为h+h' 对于本题,维护最大高度h和all 对于平面的x轴维护一棵线段树t1,每个t1的节点维护对应y轴的两棵 ...
- 洛谷P3586 [POI2015]LOG(贪心 权值线段树)
题意 题目链接 Sol 显然整个序列的形态对询问没什么影响 设权值\(>=s\)的有\(k\)个. 我们可以让这些数每次都被选择 那么剩下的数,假设值为\(a_i\)次,则可以\(a_i\)次被 ...
- 2018.08.11 洛谷P3224 [HNOI2012]永无乡(线段树合并)
传送门 给出n个带点权的点,支持连边和查询连通块第k大. 这个貌似就是一道线段树合并的裸板啊... 代码: #include<bits/stdc++.h> #define N 100005 ...
随机推荐
- python的参数传递是值传递还是引用传递??
函数参数传递机制,传值和引用的是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传递. 值传递(pa ...
- sql常用的统计公式
hivesql中max,min函数不能作用于多列,因此在有上下门限区间限制时多用公式直接计算. max(x,y)=(x+y+ABS(x-y))/2 min(x,y)=(x+y-ABS(x-y))/2 ...
- python中常用的导包的方法和常用的库
python中常用的导包的方法 导入包和包名的方法:1.import package.module 2.from package.module import * 例一: ...
- Python 做简单的登录系统
案例 之 登录系统原创作品1 该随笔 仅插入部分代码:全部py文件源代码请从百度网盘自行下载! 链接:https://pan.baidu.com/s/1_sTcDvs5XEGDcnpoQEIrMg 提 ...
- Linux信号处理编程
01. 学习目标 了解信号中的基本概念 熟练使用信号相关的函数 了解内核中的阻塞信号集和未决信号集作用 熟悉信号集操作相关函数 熟练使用信号捕捉函数signal 熟练使用信号捕捉函数sigaction ...
- Hadoop MapReduce 保姆级吐血宝典,学习与面试必读此文!
Hadoop 涉及的知识点如下图所示,本文将逐一讲解: 本文档参考了关于 Hadoop 的官网及其他众多资料整理而成,为了整洁的排版及舒适的阅读,对于模糊不清晰的图片及黑白图片进行重新绘制成了高清彩图 ...
- 【UE4 C++】绘制函数 Debug drawing functions
基于UKismetSystemLibrary /** Draw a debug line */ UFUNCTION(BlueprintCallable, Category="Renderin ...
- 使用json-path解析json
在我们的日常开发中,有时候需要从一个json字符串中获取一个值,或者从一段json字符串中获取到某些值,如果先使用Gson或Jackson转换成java对象在获取值,有些时候是很麻烦的,那么有没有一种 ...
- spring security实现简单的url权限拦截
在一个系统中,权限的拦截是很常见的事情,通常情况下我们都是基于url进行拦截.那么在spring security中应该怎么配置呢. 大致步骤如下: 1.用户登录成功后我们需要拿到用户所拥有的权限,并 ...
- 深入理解Linux C语言内存管理
问题不能拖,我这就来学习一下吧,争取一次搞定. 在任何程序设计环境及语言中,内存管理都十分重要. 内存管理的基本概念 分析C语言内存的分布先从Linux下可执行的C程序入手.现在有一个简单的C源程序h ...