动态规划训练之十

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

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

code

#include
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

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

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

可是加了这个条件就很烦

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

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

明显就只有权值线段树

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

不同的前缀和有750*750个

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

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

code:

#include 
#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
#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

你可能感兴趣的:(动态规划训练之十)