zoukankan      html  css  js  c++  java
  • 牛客练习赛78 E CCA的区间

    https://ac.nowcoder.com/acm/contest/11168/E

    如果没有区间翻转操作

    那就直接枚举区间左或右端点,

    因为要求数不能重复,每个数字又都是2的幂

    所以固定一个端点后,区间长度是log(值域)级别的,这里就是24

    可以翻转一个区间,相当于可以选任意2个不相交的区间

    这里的不相交指的是位置不相交

    由于2个区间无重复数字一定能得出2个区间位置不相交

    而有重复数字且区间不相交是不合法的情况

    所以相当于选2个无重复(区间内和区间之间)数字的区间

    这可以用状压dp求解

    按照最开始说的可以先求出dp[i]=i,表示有一个无重复数字区间,它的数字和为i

    然后求出dp[i]=x,表示状态i的子集里最大的数字和

    可以通过从小到大枚举所有状态i,逐次去掉i的一个2的幂次求

    最后求所有的max(dp[i]+dp[总状态 ^ i])

    #include<cstdio>
    #include<algorithm> 
    
    using namespace std;
    
    #define N 100001
    
    int a[N],dp[1<<24];
    
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        int s;
        for(int i=1;i<=n;++i)
        {
            s=0;
            for(int j=i;j;--j)
            {
                if(a[j]&s) break;
                s|=a[j];
                dp[s]=s;
            }
        }
        s=(1<<24)-1;
        for(int i=1;i<=s;++i)
            for(int j=0;j<=23;++j)
                if(i&1<<j) dp[i]=max(dp[i],dp[i^1<<j]);
        int ans=0;
        for(int i=1;i<=s;++i) ans=max(ans,dp[i]+dp[s^i]);
        printf("%d",ans);
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    code3728 联合权值
    Codevs 4600 [NOI2015]程序自动分析
    code1540 银河英雄传说
    code1074 食物链
    堆排序
    哈夫曼树与哈夫曼码
    优先队列用法
    code1154 能量项链
    code1225 八数码Bfs
    javascript5
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/14537283.html
Copyright © 2011-2022 走看看