• P6144 [USACO20FEB]Help Yourself P(DP+线段树)


    P6144 [USACO20FEB]Help Yourself P

    将线段按照了 \(r\) 排序,设右端点为 \(r\) 的答案为 \(f_r\),发现这样转移非常困难。

    \(\color{yellow}{\bigstar\texttt{Trick}}\):区间覆盖的题要按照左端点排序,记右端点为 \(r\) 时的答案为 \(f_r\)

    考虑 \(k=1\) 时怎么做,加入一条线段,

    • 对于 \([1,l-1]\)合法 \(f_i\),可以连通块个数加上 \(1\) 累加到 \(f_r\)
    • 对于 \([l,r]\)\(f_i\) 直接累加到 \(f_r\)
    • 对于 \([r+1,n]\)\(f_i\) 数值乘上 \(2\) 后累加到 \(f_i\),这条线段可以选或不选。

    对于 \(k>1\),维护答案的 \([0,k]\)的所有值 ,\(x^k\rightarrow (x+1)^k=\sum_{i=0}^k\binom{k}{i}x^i\),预处理系数后 \(\mathcal{O(k)}\) 加即可。

    #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;
    }
    
  • 相关阅读:
    QQ家园熄灭不了解决方法
    那时我们还年轻[转]
    QQ游戏图标熄灭大全
    FlashDevelop快捷键
    linux 全局搜索某一文件并将文件内容并进行替换的命令
    navigate 10.0.5 regist cn
    线程、socket、stl 以及并发设计
    drupal真不错
    网卡问题解决思路linux版
    socket错误:Program received signal SIGPIPE, Broken pipe
  • 原文地址:https://www.cnblogs.com/EricQian/p/16585894.html
Copyright © 2020-2023  润新知