• [BZOJ] 5125: [Lydsy1712月赛]小Q的书架


    按颜神犇PPT上分治树的思想,大胆考虑一个区间DP,发现可以写成序列形式,也就是

    [f[i][j]=min{f[k][j-1]+cost[k+1][i]} ]

    (f[i][j])表示前i个数,分成了(j)段,其中(cost[i][j])代表区间([i,j])的逆序对数

    对于一个固定的(i)一个劣决策(k_1)永远会劣于一个好决策(k_2),即逆序对数减少速不会快于(k_2),具有显然的决策单调性

    板板讲过,形如

    [f[i]=min/max{g[j]+cost[j][i]} ]

    的DP式,如果(cost)满足四边形不等式(也就是决策单调),那么不仅可以采用一般的单调栈维护决策单调性,还可以采用分治的方法,而且这种分治好写得多

    更一般地,即使是(f[i][j])一样的状态,只要(f[i][j])只依赖(f[i][j-1]),那么它们本质上就是分开的(f)(g),同样可以做

    然而这里区间逆序对不会求,看了题解.....

    题解采用了树状数组(log)时间维护单点,使用类似莫队move的方法,复杂度应该和分治有关,不会证,存疑

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    inline int rd(){
      int ret=0,f=1;char c;
      while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
      while(isdigit(c))ret=ret*10+c-'0',c=getchar();
      return ret*f;
    }
    
    const int MAXN = 40005;
    
    int n,m,a[MAXN];
    
    int t[MAXN];
    int query(int x){
      int ret=0;
      for(int i=x;i;i-=i&-i)ret+=t[i];
      return ret;
    }
    void update(int x,int w){
      for(int i=x;i<=n;i+=i&-i)t[i]+=w;
    }
    
    int cur;
    void move(int aiml,int aimr){
      static int L=1,R;
      while(L<aiml){update(a[L],-1);cur-=query(a[L]-1);L++;}
      while(L>aiml){L--;update(a[L],1);cur+=query(a[L]-1);}
      while(R<aimr){R++;update(a[R],1);cur+=(R-L+1)-query(a[R]);}
      while(R>aimr){update(a[R],-1);cur-=(R-L)-query(a[R]-1);R--;}
    }
    
    int f[MAXN],g[MAXN];
    void solve(int l,int r,int sl,int sr){
      if(l>r)return;
      int mid=(l+r)>>1,mn=1<<30,p=sl;
      for(int i=sl;i<=sr&&i<mid;i++){
        move(i+1,mid);
        if(f[i]+cur<mn){mn=f[i]+cur;p=i;}
      }
      g[mid]=mn;
      solve(l,mid-1,sl,p);
      solve(mid+1,r,p,sr);
    }
    
    int main(){
      n=rd();m=rd();
      for(int i=1;i<=n;i++){a[i]=rd();}
      for(int i=1;i<=n;i++){move(1,i);f[i]=cur;}
      for(int i=1;i<m;i++){
        solve(1,n,1,n);
        memcpy(f,g,sizeof(g));
      }
      cout<<f[n];
      return 0;
    }
    
    
    未经许可,禁止搬运。
  • 相关阅读:
    剑指offer编程题66道题 26-35
    剑指offer编程题66道题 1-25
    springboot的自动配置
    用智能的编译器来防错
    实现迭代器的捷径
    结束C#2的讲解:最后的一些特性
    进入快速委托通道
    可空类型
    用泛型实现参数化类型
    C#1所搭建的核心基础
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9791518.html
Copyright © 2020-2023  润新知