1. 程式人生 > 其它 >二進位制的世界 題解

二進位制的世界 題解

link

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
*/