zoukankan      html  css  js  c++  java
  • 常州day1p3

    给定一个 n 行 m 列的方格,每个格子里有一个正整数 a,1 ≤ a ≤ k,k ≤ n∗m 假设你当前时刻站在 (i,j) 这个格子里,你想要移动到 (x,y),那必须满足以下三个条件 1:i < x 2:j < y 3:第 i 行第 j 列格子里的数不等于第 x 行第 y 列格子里的数 求从 (1,1) 移动到 (n,m) 的不同的方案数 

    对于 100% 的数据,n,m ≤ 750

    容易想到f[i][j]=sigma(f[k][l]|a[k][l]!=a[i][j])

    我们可以容易的统计和颜色无关的情况然后去掉颜色相同的就可以了。

    于是我们对每一种颜色建立一颗权值线段树

    动态开点

    时间复杂度O(n^2logn)

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<queue>
    #include<set>
    #include<map>
    #include<vector>
    #define re register
    #define il inline
    using namespace std;
    const int N=1001,NN=8000001;
    const int mod=1000000007;
    int n,m,a[N][N],k,root[NN],lch[NN],rch[NN],cnt=0;
    int f[N][N],s[N][N],w[NN];
    il int read(){
        re int hs=0;re char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)){
            hs=(hs<<3)+(hs<<1)+c-'0';
            c=getchar(); 
        }
        return hs;
    }
    il void add(re int &i,re int l,re int r,re int p,re int v){
        if(i==0) i=(++cnt);
        w[i]=(w[i]+v)%mod;
        if(l==r) return;
        re int mid=(l+r)/2;
        if(p<=mid) add(lch[i],l,mid,p,v);
        else add(rch[i],mid+1,r,p,v); 
    }
    il int sum(re int i,re int l,re int r,re int p,re int q){
        if(!i) return 0;
        if(l==p&&r==q) return w[i];
        re int mid=(l+r)/2;
        if(q<=mid) return sum(lch[i],l,mid,p,q);
        if(mid<p) return sum(rch[i],mid+1,r,p,q);
        return (sum(lch[i],l,mid,p,mid)+sum(rch[i],mid+1,r,mid+1,q))%mod; 
    }
    int main(){
        freopen("hopscotch.in","r",stdin);
        freopen("hopscotch.out","w",stdout);
        n=read();m=read();k=read();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++)
                a[i][j]=read();
        }
        f[1][1]=1;add(root[a[1][1]],1,m,1,f[1][1]);
        for(int i=1;i<=m;i++) s[1][i]=1;
        for(int i=1;i<=n;i++) s[i][1]=1;
        for(int i=2;i<=n;i++){
            for(int j=2;j<=m;j++){
                f[i][j]=(s[i-1][j-1]-sum(root[a[i][j]],1,m,1,j-1)+mod)%mod;
                s[i][j]=(((s[i-1][j]+s[i][j-1])%mod+f[i][j])%mod-s[i-1][j-1]+mod)%mod;
                add(root[a[i-1][j]],1,m,j,f[i-1][j]);
            }
        }
        cout<<f[n][m]%mod;
        return 0;
    }
  • 相关阅读:
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    《鸟哥的Linux私房菜》读书笔记
    w命令集合
  • 原文地址:https://www.cnblogs.com/ExiledPoet/p/5771471.html
Copyright © 2011-2022 走看看