zoukankan      html  css  js  c++  java
  • 动态规划训练之十

    https://www.luogu.org/problem/P3120

    首先ON^4的dp很容易想到(数据加强过,所以这个过不了)

    code

    #include<bits/stdc++.h>
    using namespace std;
    int r,c,k;                              //行,列,数值限定 
    int a[751][751];
    long long f[751][751]={0};           
    //f[i][j]:左上f[i][j]严格左上方所有点的路径总数之和 
    int main()
    {
        scanf("%d%d%d",&r,&c,&k);
        for(int i=0;i<r;i++)
            for(int j=0;j<c;j++)
                scanf("%d",&a[i][j]);
        f[0][0]=1;
        for(int i=0;i<r;i++)
            for(int j=0;j<c;j++)            //要计算的点 
                for(int p=0;p<i;p++)
                    for(int q=0;q<j;q++)    //左上方的点 
                        if(a[i][j]!=a[p][q])//审题:要求数值不同 
                            f[i][j]=(f[i][j]+f[p][q])%1000000007;
                                            //勿忘mod 1000000007  
        cout<<f[r-1][c-1]<<endl;
        return 0;
    }
    

    加强的数据完美卡到N^2*logN

    首先如果没有两点的val值不同这个条件的话,直接维护二维前缀和就好

    可是加了这个条件就很烦

    还是考虑前缀和,两点的val值不同,那就先考虑两点val值相同的情况

    跟新答案时,用所有的前缀和减掉相同的情况就好

    明显就只有权值线段树

    可是不同的val值可能有750*750个

    不同的前缀和有750*750个

    开不下啊,怎么办?,于是考虑动态开点

    就愉(tong)快(ku)的AC了

    code:

    #include <bits/stdc++.h>
    #define y1 y1_
    #define index index_
    #define pipe pipe_
    #define next next_
    #define endl '
    '
    #define rgi register int
    #define ll long long
    #define Pi acos(-1.0)
    #define lowbit(x) ((x&(-x)))
    #define pb push_back
    #define mk make_pair
    #define pii pair<int,int>
    #define fst first
    #define scd second
    using namespace std;
    inline int read() {
        int f=1,x=0;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int MAXN=755;
    const int MOD=1e9+7;
    int n,m,K,a[MAXN][MAXN];
    struct SegmentTree{
        int ls,rs; ll sum;
    }t[MAXN*MAXN*10];
    int cnt;
    void update(int l,int r,int &rt,int pos,int val) {
        if(!rt) rt=++cnt;
        if(l==r) {
            t[rt].sum=(t[rt].sum+val)%MOD;
            return ;
        }
        int mid=(l+r)>>1;
        if(pos<=mid) update(l,mid,t[rt].ls,pos,val);
        else update(mid+1,r,t[rt].rs,pos,val);
        t[rt].sum=(t[t[rt].ls].sum+t[t[rt].rs].sum)%MOD;
    }
    ll sum[MAXN],dp[MAXN][MAXN];
    ll query(int l,int r,int rt,int pos) {
        if(!rt) return 0;
        if(r<=pos) return t[rt].sum;
        int mid=(l+r)>>1;
        if(pos<=mid) return query(l,mid,t[rt].ls,pos);
        else return (query(l,mid,t[rt].ls,pos)+query(mid+1,r,t[rt].rs,pos))%MOD;
    }
    int main() {
    //  freopen("","r",stdin);
    //  freopen("","w",stdout);
        ios::sync_with_stdio(0);cin.tie(0);/*syn加速*/
        n=read(); m=read(); K=read(); cnt=K;
        for(rgi i=1;i<=n;++i) for(rgi j=1;j<=m;++j) a[i][j]=read();
        for(rgi i=1;i<m;++i) sum[i]=1;
        dp[1][1]=1; update(1,m,a[1][1],1,dp[1][1]);
        for(rgi i=2;i<=n;++i) {
            for(rgi j=2;j<=m;++j) {
                dp[i][j]=(sum[j-1]-query(1,m,a[i][j],j-1)+MOD)%MOD;
            }
            ll tmp=0;
            for(rgi j=2;j<=m;++j) {
                tmp=(tmp+dp[i][j])%MOD;
                sum[j]=(sum[j]+tmp)%MOD;
                update(1,m,a[i][j],j,dp[i][j]);
            }
        }
        cout<<dp[n][m]<<endl;
        return 0;
    }
    
  • 相关阅读:
    如何检测死锁并快速定位死锁位置
    几种线程本地存储变量和普通变量的性能比较
    multi_index_container性能测试
    [高并发引擎]定时器模块
    [高并发引擎]Log模块
    静态博客教程 1:hexo + github
    蛇形填数
    实现简单的 ls 命令
    静态库与动态库的创建和使用
    用两个栈实现队列
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/11646729.html
Copyright © 2011-2022 走看看