[状压dp][平衡规划] Jzoj P4616 二进制的世界

Description

 

Input

Output

 

Sample Input

5 and 1
3 5 2 7 1

Sample Output

1 1
2 1
5 1
1 3
 

Data Constraint

 

题解

  • 对于普通的暴力,因为ai小于等于2^16,所以暴力做可以做到加入O(1),而查询O(2^16),显然是不可以的
  • 考虑把两个操作平衡一下,f[x][y]表示前半段为x,后半段的数与y运算的最大值,g[x][y]记录个数
  • 我们在加入一个数时,我们枚举j,设该数前8位为a,后8位为b来更新f[a][j]
  • 查询时,设该数前8位为a,后8位为b,我们可以枚举i用f[i][b]|((i~a)<<8)更新答案即可
  • 复杂度为O(2^8*n)

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 using namespace std;
 5 const int N=1e5+10,M=256;
 6 int n,type,sum,ans,a[N],f[M][M],g[M][M];
 7 char s[10];
 8 int calc(int x,int y) { return s[0]=='o'?x|y:(s[0]=='a'?x&y:x^y); }
 9 int main()
10 {
11     freopen("binary.in","r",stdin),freopen("binary.out","w",stdout);
12     scanf("%d%s%d",&n,&s,&type);
13     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
14     for (int i=1;i<=n;i++)
15     {
16         int k=a[i]&255;
17         if (i>1)
18         {
19             sum=ans=0;
20             for (int j=0;j<=255;j++)
21                 if (g[j][k])    
22                 {
23                     if ((f[j][k]|calc(j,a[i]>>8)<<8)==ans) sum+=g[j][k];
24                     else if ((f[j][k]|calc(j,a[i]>>8)<<8)>ans) ans=f[j][k]|calc(j,a[i]>>8)<<8,sum=g[j][k];
25                 }
26             if (type==1) printf("%d %d\n",ans,sum); else printf("%d\n",ans); 
27         }
28         for (int j=0;j<=255;j++) if (f[a[i]>>8][j]==calc(j,k)) g[a[i]>>8][j]++; else if (f[a[i]>>8][j]<calc(j,k)) f[a[i]>>8][j]=calc(j,k),g[a[i]>>8][j]=1;            
29     }
30 }

 

posted @ 2019-07-03 16:33  BEYang_Z  阅读(272)  评论(0)    收藏  举报