CCA range (thinking + state pressure/sosdp)

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


Idea: Reversing an interval means that any two consecutive intervals can be spliced ​​together

So the question becomes what is the maximum sum of the two largest disjoint subintervals. Considering that the value is at the log level, it is converted to a value.

Regard the state of a legal interval as binary and perform state pressure. Due to the exponential level, the second for at most runs 24 times and it ends.

So nlogn can process all the binary numbers in the sequence.

The problem becomes to find the maximum value of x^y under the condition of two numbers x, y, x&y==0.

Then preprocess the maximum subset of each binary state in the interval. Recorded as the largest subset of dp[j]:j.

The final answer is dp[j]+dp[ ((1<<24 )-1) ^j]

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+100;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL a[maxn];
LL dp[1<<25];///dp[j]:j的最大子集
int main(void)
{
  LL n;n=read();
  for(int i=1;i<=n;i++) cin>>a[i];
  for(int i=1;i<=n;i++){
     LL res=0;
     for(int j=i;j<=min(n,(LL)i+27);j++){
        if(a[j]&res) break;
        res|=a[j];
        dp[res]=res;
     }
  }
  ///预处理每一个二进制状态的子集的最大值
  for(int i=0;i<24;i++){///枚举某一个二进制位置取反的子集;
     for(LL j=0;j<(1<<24);j++){
        if(( j&(1<<i) ) ){
            dp[j]=max(dp[j],dp[j^(1LL<<i)]);
        }
     }
  }
  LL ans=0;
  LL M=(1<<24)-1;
  for(LL i=0;i<(1<<24);i++){
    ans=max(ans,dp[i]+dp[M^i]);
  }
  printf("%lld\n",ans);
return 0;
}

 

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/115186190