题解 最大或
第一眼看是个数位DP,略慌,确定DP方案后一小时码完并过拍
但其实麻烦了,有更优策略:
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;
}