codeforces1208F Bits And Pieces

https://codeforces.com/contest/1208/problem/F

First of all, it must enumerate a[i] and then find the largest (a[k]&a[j]) that can make a[i] or up, because a[j]&a[k] is bound.

Then the question is transformed into how to quickly find the largest (a[k]&a[j]) that can make a[i], then we consider from high to low, if this bit a[i] is 0, then sure If you want to make the answer bigger, you just need to see if there are two numbers in the superset of this one and their positions are on the right side of i.

So obviously the problem is transformed into a high-dimensional prefix sum of a superset. Each digit records the position of the last two digits as a subset. Suppose it is mx[i],sec[i], if sec [i] If both are greater than the current enumeration position, it means that there is a solution to change this bit to 1.

Consider from the high position to the low position, if it can work, add this one, and don’t care if it doesn’t work.

There are still too few things. . . I feel that as long as I know the high-dimensional prefix and this kind of F questions, I can do it casually.

#include<bits/stdc++.h>
using namespace std;

const int maxl=3e6+10;

int n,ans;
int a[maxl];
int mx[maxl],sec[maxl];

inline void upd(int i,int x)
{
	if(x>mx[i])
		sec[i]=mx[i],mx[i]=x;
	else if(x>sec[i])
		sec[i]=x;
}

inline void prework()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{	
		scanf("%d",&a[i]);
		upd(a[i],i);
	}
	int up=1<<21;
	for(int j=0;j<20;j++)
		for(int i=0;i<up;i++)
		if(!((i>>j)&1))
		{
			upd(i,mx[i^(1<<j)]);
			upd(i,sec[i^(1<<j)]);
		}
}

inline void mainwork()
{
	int now;ans=0;
	for(int i=1;i<=n-2;i++)
	{
		now=0;
		for(int j=20;j>=0;j--)
		{
			if((a[i]>>j)&1)
				continue;
			if(sec[now^(1<<j)]>i)
				now^=(1<<j);
		}
		ans=max(ans,now|a[i]);
	}
}

inline void print()
{
	printf("%d",ans);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

Guess you like

Origin blog.csdn.net/liufengwei1/article/details/108251211