把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

ARC141D Non-divisible Set

题面传送门
神仙题,被踩爆了/kk
首先证明一个结论:\(\{1,2,\dots 2m\}\)中,按照这样的最大独立集,答案为\(m\)
首先证明下界,显然是\(\{m+1,m+2,\dots 2m\}\)这样的一组合法解。
然后证明上界,我们将每个数的\(2\)都除掉,就只剩下\(m\)个数,这\(m\)个数中显然不能有两个同组的,所以答案上限为\(m\)
这启发我们相当于选择\(m\)\(k_i\),满足对于任意\(i,j\),\(2^{k_i}(2i-1)\)不是\(2^{k_j}(2j-1)\)的倍数。
如果\(2i-1\)不是\(2j-1\)的倍数,那么相当于没有限制,否则相当于\(k_i<k_j\)
然后每个位置可以处理出来一个\(k\)的上界和下界,显然在这之间的每个都是可以的,然后就可以做到\(O(n+m\log m)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (600000+5)
#define M (100000+5)
#define K (600+5)
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-9)
#define ull unsigned ll
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (1ll*rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;vector<int> W[N];
int n,m,A[N],Fl[N],G[N],x,P[N],L[N],R[N];
int main(){
	freopen("1.in","r",stdin);freopen("2.out","w",stdout);
	int i,j,h;scanf("%d%d",&n,&m);for(i=1;i<=n;i++) scanf("%d",&A[i]);for(i=1;i<=2*m;i++) {Fl[i]=i;while(Fl[i]%2==0) Fl[i]/=2,G[i]++;}
	for(i=1;i<=n;i++) W[Fl[A[i]]].PB(G[A[i]]);Me(R,0x3f);Me(L,-1);for(i=1;i<=2*m;i+=2){
		if(LB(W[i].begin(),W[i].end(),R[i])==W[i].begin()){while(n--) puts("No");return 0;}
		R[i]=*(--LB(W[i].begin(),W[i].end(),R[i]));for(j=2*i;j<=2*m;j+=i) R[j]=min(R[j],R[i]);
	}
	for(i=2*m-1;i>=0;i-=2){
		for(j=i*2;j<=2*m;j+=i) L[i]=max(L[i],L[j]);if(UB(W[i].begin(),W[i].end(),L[i])==W[i].end()) {while(n--) puts("No");return 0;}
		L[i]=*(UB(W[i].begin(),W[i].end(),L[i]));
	}
	for(i=1;i<=n;i++) puts(G[A[i]]>=L[Fl[A[i]]]&&G[A[i]]<=R[Fl[A[i]]]?"Yes":"No");
}
posted @ 2022-05-30 19:23  275307894a  阅读(78)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end