zoukankan      html  css  js  c++  java
  • BZOJ 3939 [Usaco2015 Feb]Cow Hopscotch ——线段树 CDQ分治

    显然dp[i][j]=ps[i-1][j-1]-sigma(dp[k<i][l<j],a[i][j]=a[k][l])

    考虑对于每一种颜色都开一颗区间线段树,但是空间不够。

    所以我们可以动态开节点的权值线段树即可。

    因为ij写反了调了30min。

    然后发现空间的问题我们可以分治啊,按照纵坐标分治,然后处理左半边对右半边的影响即可。

    然后CDQ分治即可,空间是O(nm)的,时间复杂度是O(nmlogm)的。

    复杂度怎么算?主定理套用即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define md 1000000007
    int sum[6000001],ls[6000001],rs[6000001],tot=0;
    struct Dynamic_Segment_Tree{
    	int L,R,rt,X,C;
    	void init(){rt=0;}
    	int query(int x,int l,int r)
    	{
    		if (l>r) return 0;
    		if (!x) return 0;
    		int mid=l+r>>1;
    		if (L<=l&&r<=R) return sum[x];
    		if (R<=mid) return query(ls[x],l,mid);
    		else if (L>mid) return query(rs[x],mid+1,r);
    		else return (query(ls[x],l,mid)+query(rs[x],mid+1,r))%md;
    	}
    	void update(int x)
    	{
    		sum[x]=(sum[ls[x]]+sum[rs[x]])%md;
    	}
    	void modify(int &x,int l,int r)
    	{
    		if (!x) x=++tot;
    		int mid=l+r>>1;
    		if (l==r)
    		{
    			(sum[x]+=C)%=md;
    			return ;
    		}
    		if (X<=mid) modify(ls[x],l,mid);
    		else modify(rs[x],mid+1,r);
    		update(x);
    	}
    }T[562501];
    int dp[751][751],prs[751][751],r,c,k,a[751][751];
    int main()
    {
    	scanf("%d%d%d",&r,&c,&k);
    	F(i,1,r) F(j,1,c) scanf("%d",&a[i][j]);
    	F(i,1,k) T[i].init();
    	dp[1][1]=1;
    	F(i,1,r)
    	{
    		F(j,1,c)
    		{
    			(dp[i][j]+=prs[i-1][j-1])%=md;
    			T[a[i][j]].L=1;T[a[i][j]].R=j-1;
    			if (j>=2) (dp[i][j]=dp[i][j]-T[a[i][j]].query(T[a[i][j]].rt,1,c)+md)%=md;
    			prs[i][j]=(((prs[i][j-1]+prs[i-1][j])%md+dp[i][j])%md-prs[i-1][j-1]+md)%md;
    		}
    		F(j,1,c)
    		{
    			T[a[i][j]].X=j;T[a[i][j]].C=dp[i][j];
    			T[a[i][j]].modify(T[a[i][j]].rt,1,c);
    		}
    	}
    	printf("%d
    ",dp[r][c]);
    }
    

    CDQ分治

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define md 1000000007
    int a[751][751],n,m,k,sum[1000005],dp[751][751],ps[751];
    void CDQ(int l,int r)
    {
    	if (l==r) return;
    	int mid=l+r>>1;
    	CDQ(l,mid);
    	F(i,1,n-1)
    	{
    		F(j,l,mid)
    		{
    			(sum[a[i][j]]+=dp[i][j])%=md;
    			(ps[i]+=dp[i][j])%=md;
    		}
    		(ps[i]+=ps[i-1])%=md;
    		F(j,mid+1,r)
    		{
    			(dp[i+1][j]+=ps[i])%=md;
    			dp[i+1][j]=(dp[i+1][j]-sum[a[i+1][j]]+md)%md;
    		}
    	}
    	F(i,1,n)
    	{
    		ps[i]=0;
    		F(j,l,mid) sum[a[i][j]]=0;
    	}
    	CDQ(mid+1,r);
    }
    int main()
    {
    	scanf("%d%d%d",&n,&m,&k);
    	F(i,1,n) F(j,1,m) scanf("%d",&a[i][j]);
    	dp[1][1]=1;
    	CDQ(1,n);
    	printf("%d
    ",dp[n][m]);
    }
    

      

  • 相关阅读:
    正则表达式
    jdbc,链接调用数据库的方法——例题
    python字符串操作
    python条件判断
    python运算符
    python中输入输出
    python关键字与标识符
    python变量
    python注释
    安装django报错一直安装不上?
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6587022.html
Copyright © 2011-2022 走看看