zoukankan      html  css  js  c++  java
  • 【UNR #4】序列妙妙值 分块+DP

    只会 80pts.  

    最裸的暴力(40pts)   

    令 $f[i][j]$ 表示当前 DP 到 $i$,划分成了 $j$ 段的最小值.  

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

    一点优化(60 ~ 80pts) 

    有几个测点 $a[i]$ 很小,那么可以直接开一个桶 $s[i][j]$ 表示前缀异或和为 $i$,且划分 $j$ 段的最小值.   

    修改复杂度:$O(1)$,查询复杂度 $O(v)$,总复杂度 $O(nv)$.   

    还可以在 $trie$ 树上乱搞,不知道能拿多少分.   

    正解

    分块.   

    我们发现 $60$ 分解法中查询和修改复杂度差异很大,所以考虑用分块去平衡上述复杂度.  

    由于数字最大是 $2^{16}$,所以考虑维护 $mi[x][y]$ 表示一个数的前 $8$ 位是 $x$,去匹配一个后 $8$ 位为 $y$ 的贡献.  

    那么这个修改起来的话只需要枚举后面的 $y$,复杂度为 $O(sqrt v)$.   

    查询的话后面是固定的,然后枚举前面的 $x$,复杂度为 $O(sqrt v)$.  

    总复杂度就是 $O(nK sqrt v)$ 的.   

    代码: 

    #include <cstdio>
    #include <cstring>
    #include <algorithm>  
    #define N 60009  
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin)
    using namespace std;  
    const int inf=1000000000; 
    int n,K; 
    int a[N],f[N],tmp[N],mi[300][300];    
    int main() { 
        // setIO("input");   
        scanf("%d%d",&n,&K);   
        for(int i=1;i<=n;++i) { 
            scanf("%d",&a[i]);      
            a[i]^=a[i-1];   
        }           
        f[0]=0; 
        for(int i=1;i<=n;++i) { 
            f[i]=inf; 
        } 
        int B=(1<<8)-1;     
        for(int i=1;i<=K;++i) { 
            for(int x=0;x<256;++x) {    
                for(int y=0;y<256;++y) mi[x][y]=inf; 
            }  
            for(int j=0;j<=n;++j) { 
                tmp[j]=inf;   
                for(int x=0;x<256;++x) {    
                    //  前面固定,后面是猜的
                    int det=mi[x][a[j]&B]+((a[j]>>8^x)<<8);  
                    tmp[j]=min(tmp[j],det);     
                }     
                for(int x=0;x<256;++x) {    
                    int cur=mi[a[j]>>8][x];    
                    int det=f[j]+((a[j]&255)^x);  
                    mi[a[j]>>8][x]=min(mi[a[j]>>8][x],det);  
                }
            }         
            for(int j=0;j<=n;++j) f[j]=tmp[j];  
        }              
        for(int i=K;i<n;++i) printf("%d ",f[i]);   
        printf("%d",f[n]); 
        printf("
    ");  
        return 0;
    }
    

      

  • 相关阅读:
    web.xml中openEntityManagerInViewFilter的作用(转)
    JNDI解读(转)
    Java读取大文件的高效率实现
    快速入门react
    谈一谈我所了解的https
    漫谈JWT
    Java 中的几种线程池这么用才是对的
    用Vue来实现图片上传多种方式
    一个页面从输入URL到页面加载显示完成,这个过程都发生什么?
    “===”与“==”的区别
  • 原文地址:https://www.cnblogs.com/guangheli/p/13490781.html
Copyright © 2011-2022 走看看