CSP模拟4

A.最长上升子序列

要求字典序最小,直接贪心。

先在1~k-1 序列1构造,每次在原序列右边放上未被选的数的比它小的数。
剩下的a[k]和未被选的数倒叙输出,即可保证字典序最小。


B.独特序列

一开始题都没读懂,样例1都没想明白

样例1

3
1 2 1

因为(1) 是可以选\(i=1和i=3\)所以不可以单选(1),但可以选(1,1),因为要满足序号递增。

\(dp[i]\) 是前 \(i\) 个以 \(a[i]\) 结尾的独特序列的数量。\(last _{a[i]}\) 是 $ a[i] $上一次出现的位置,显然 \(last _{a[i]}\) 之前的不可选。所以其会有 $ last[i] $ 以后的更新到。拿个树状数组维护前缀和就好了。


C.最大GCD

离正解就差个前缀和……

如果 \(k\) 足够的就可以把序列都更新到大于等于最大值的一个数。

如果 \(k\) 不足够大直接暴力枚举 gcd 算出所有的数做出的贡献与 \(k\) 进行比较。


D.连续子段

搜挂了。

状压DP.

先贪心考虑。。。 我们把 1~k 挪到一起然后算一个逆序对。

$ f _{i,s} $ 是第 $ i $ 位,状态为 $ j $ 的 次数。一个位置可以选可以不选
选贡献为逆序对,不选贡献为min(左边移到右边,右边移到左边)的步数。
对于逆序对因为要满足单调递增所以可以用sumlow[s>>a]来算。

Code
  for(int i=1;i<=n;i++){
        int a=read();
        int M=1<<(a-1);
      
        for(int j=m;j>=0;j--){
            if(!(M&j)){
                dp[M|j]=min(dp[M|j],dp[j]+sum[j>>a]);
            }
            dp[j]=dp[j]+min(sum[j],sum[m-j]);
        }
        ans=min(ans,dp[m]);
    }
posted @   Ysz_y  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示