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 '\n' #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; }