二进制的世界 题解
Solution
考虑直接值域分块,那我们可以设 \(f(u,v)\) 表示你选的 \(a_j\) 前 \(8\) 位为 \(u\),如果 \(a_u\) 后面 \(8\) 位为 \(v\) 的答案,不难看出,我们可以 \(n\sqrt V\) 直接维护。
感觉这种做法还是挺具有普遍性的。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define MAXN
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
int n;
struct node{
int v,tot;
node operator + (const node &p)const{
if (v > p.v) return *this;
else if (v == p.v) return node{v,tot + p.tot};
else return p;
}
};
char str[5];
node f[1 << 8][1 << 8];
node queryit (int vnow,int type){
int L = vnow >> 8,R = vnow ^ (L << 8);node ans = node{0,0};
for (Int v = 0;v < (1 << 8);++ v){
int vs = (type == 1 ? (L & v) : (type == 2 ? (L | v) : (L ^ v)));
// cout << v << ": " << (vs << 8) << " , " << f[v][R].v << " & " << f[v][R].tot << endl;
if (f[v][R].tot) ans = ans + node{(vs << 8) + f[v][R].v,f[v][R].tot};
}
return ans;
}
void change (int vnow,int type){
int L = vnow >> 8,R = vnow ^ (L << 8);
for (Int v = 0;v < (1 << 8);++ v){
int vs = (type == 1 ? (R & v) : (type == 2 ? (R | v) : (R ^ v)));
if (f[L][v].tot) f[L][v] = f[L][v] + node{vs,1};
else f[L][v] = node{vs,1};
}
}
signed main(){
// freopen ("data1.in","r",stdin);
// freopen ("f1.out","w",stdout);
read (n),scanf ("%s",str + 1);int typ = str[1] == 'a' ? 1 : (str[1] == 'o' ? 2 : 3);
for (Int i = 1;i <= n;++ i){
int vnow;read (vnow);
if (i != 1){
node it = queryit (vnow,typ);
write (it.v),putchar (' '),write (it.tot),putchar ('\n');
}
change (vnow,typ);
}
return 0;
}
/*
2 or
3449 21268
*/