P6144 [USACO20FEB]Help Yourself P(DP+线段树)
P6144 [USACO20FEB]Help Yourself P
将线段按照了 排序,设右端点为 的答案为 ,发现这样转移非常困难。
:区间覆盖的题要按照左端点排序,记右端点为 时的答案为 。
考虑 时怎么做,加入一条线段,
- 对于 的合法 ,可以连通块个数加上 累加到 ;
- 对于 的 直接累加到 ;
- 对于 的 数值乘上 后累加到 ,这条线段可以选或不选。
对于 ,维护答案的 次的所有值 ,,预处理系数后 加即可。
#define Maxn 100005
#define Maxk 11
#define mod 1000000007
int n,m,k;
int C[Maxk][Maxk];
inline int MOD(int x){ return (x>=mod)?(x-mod):x; }
struct Seg
{
int l,r;
Seg(int L=0,int R=0):l(L),r(R){}
bool friend operator < (Seg x,Seg y) { return x.l<y.l; }
}s[Maxn];
struct TREE
{
int a[Maxk],muti;
TREE(){ memset(a,0,sizeof(a)),muti=1; }
inline friend TREE operator + (TREE x,TREE y)
{
TREE ret;
for(int i=0;i<=k;i++) ret.a[i]=MOD(x.a[i]+y.a[i]);
return ret;
}
inline void Push(int x)
{ for(int i=0;i<=k;i++) a[i]=1ll*a[i]*x%mod; muti=1ll*muti*x%mod; }
};
TREE tree[Maxn<<3],adx;
inline void pushdown(int p)
{
if(tree[p].muti>1)
tree[p<<1].Push(tree[p].muti),tree[p<<1|1].Push(tree[p].muti),
tree[p].muti=1;
}
void change(int p,int nl,int nr,int x)
{
if(nl==nr) { tree[p]=adx; return; }
int mid=(nl+nr)>>1; pushdown(p);
if(mid>=x) change(p<<1,nl,mid,x);
else change(p<<1|1,mid+1,nr,x);
tree[p]=tree[p<<1]+tree[p<<1|1];
}
void Times(int p,int nl,int nr,int l,int r)
{
if(nl>=l && nr<=r) { tree[p].Push(2); return; }
int mid=(nl+nr)>>1; pushdown(p);
if(mid>=l) Times(p<<1,nl,mid,l,r);
if(mid<r) Times(p<<1|1,mid+1,nr,l,r);
tree[p]=tree[p<<1]+tree[p<<1|1];
}
TREE query(int p,int nl,int nr,int l,int r)
{
if(nl>=l && nr<=r) return tree[p];
int mid=(nl+nr)>>1; pushdown(p);
if(mid>=l && mid<r)
return query(p<<1,nl,mid,l,r)+query(p<<1|1,mid+1,nr,l,r);
else if(mid<r) return query(p<<1|1,mid+1,nr,l,r);
else return query(p<<1,nl,mid,l,r);
}
int main()
{
C[0][0]=1;
for(int i=1;i<=10;i++)
{
C[i][0]=1;
for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
n=rd(),k=rd(),m=n<<1;
for(int i=1,l,r;i<=n;i++) l=rd(),r=rd(),s[i]=Seg(l,r);
sort(s+1,s+n+1); adx=TREE(),adx.a[0]=1;
change(1,0,m,0);
for(int T=1;T<=n;T++)
{
Times(1,0,m,s[T].r+1,m);
adx=query(1,0,m,0,s[T].l-1);
TREE ret;
for(int i=0;i<=k;i++) for(int j=0;j<=i;j++)
(ret.a[i]+=1ll*C[i][j]*adx.a[j]%mod)%=mod;
adx=ret+query(1,0,m,s[T].l,s[T].r);
change(1,0,m,s[T].r);
}
printf("%d\n",tree[1].a[k]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现