[状压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 }

 

转载于:https://www.cnblogs.com/Comfortable/p/11127317.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值