题解 最大或

传送门

第一眼看是个数位DP,略慌,确定DP方案后一小时码完并过拍
但其实麻烦了,有更优策略:
image

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int l, r;

namespace force{
	void solve() {
		int ans=0;
		for (int i=l; i<=r; ++i) 
			for (int j=i; j<=r; ++j) 
				ans=max(ans, i|j);
		printf("%lld\n", ans);
	}
}

namespace task1{
	int dp[65][2][2][2];
	int dfs(int u, bool lim1, bool lim2, bool same) {
		// cout<<"dfs: "<<u<<' '<<lim1<<' '<<lim2<<' '<<same<<endl;
		if (u<0) return 0;
		int *t=&dp[u][lim1][lim2][same];
		if (~(*t)) return *t;
		if (lim1 && lim2) {
			if (same) {
				if ( ((1ll<<u)&l) ^ ((1ll<<u)&r) ) {
					return *t = max(dfs(u-1, 1, 0, 1), dfs(u-1, 1, 1, 0))+(1ll<<u);
				}
				else {
					return *t = dfs(u-1, lim1, lim2, same)+((1ll<<u)&r);
				}
			}
			else {
				return *t = dfs(u-1, !((1ll<<u)&r), 0, 0)+(1ll<<u);
			}
		}
		else if (lim1 && !lim2) {
			if (same) {
				if ((1ll<<u)&r) return *t = dfs(u-1, 0, 0, 0)+(1ll<<u);
				else return *t = dfs(u-1, 1, 0, 1);
			}
			else {
				if ((1ll<<u)&r) return *t = dfs(u-1, 0, 0, 0)+(1ll<<u);
				else return *t = dfs(u-1, 1, 0, 0)+(1ll<<u);
			}
		}
		else if (!lim1 && lim2) {
			// cout<<"pos1"<<endl;
			if (same) {
				if ((1ll<<u)&l) return *t = dfs(u-1, 0, 1, 0)+(1ll<<u);
				else return *t = dfs(u-1, 0, 0, 0)+(1ll<<u);
			}
			else {
				// if ((1ll<<u)&l) return *t = dfs(u-1, 0, )
			}
		}
		else { // !lim1 && !lim2
			// assert(!same);
			return *t = dfs(u-1, 0, 0, 0)+(1ll<<u);
		}
		// puts("error");
		return 0;
	}
	void solve() {
		memset(dp, -1, sizeof(dp));
		printf("%lld\n", dfs(63, 1, 1, 1));
	}
}

signed main()
{
	freopen("maxor.in", "r", stdin);
	freopen("maxor.out", "w", stdout);

	int T=read();
	while (T--) {
		l=read(); r=read();
		// force::solve();
		task1::solve();
	}

	return 0;
}
posted @ 2021-10-15 21:43  Administrator-09  阅读(1)  评论(0编辑  收藏  举报