AtCoder Regular Contest 141 D,E
D
很有趣的一题。
首先注意到一个不同寻常的条件\(M\leq N\leq 2M\),这启发我们去想有关奇偶的结论。
我们将每个数剖开所有\(2\)的因子,即\(a_{i}=b_{i}2^{c_{i}}\),其中\(b_{i}\)是奇数。比如\(a_{i}=12=3\times 2^2\),此时\(b_{i}=3,c_{i}=2\)
那么若对于\(i,j\),且\(i\neq j\),\(b_{i}=b_{j}\),那么我们只能选择其中的一个。(因为它们互为倍数)
也就是,对于每个\(b\),我们只能选择一个,而我们现在最少要选择\(\frac{n}{2}\)个(\(N\leq 2M\)),且\(b\)最大也就\(2M-1\)(\(a_{i}\leq 2M\))。所以对于每个不同的\(b\),我们必须从中选择一个。
如果对于奇数\(i\)满足\(1\leq i\leq 2M\),且没有任何一个\(j\),满足\(b_{j}=i\),那无论如何我们都选择不了\(M\)个,所以全部输出\(No\)。
但注意,比如像\(b_{i}=1\)和\(b_{j}=3\)之间也可能出现倍数关系(比如\(2\)和\(6\)),这里,若\(b_{i}<b_{j}\),且\(b_{i}\)是\(b_{j}\)的因子,那么\(c_{j}\)必须小于\(c_{i}\),。(比如我们不能选择\(2\)和\(6\),因为\(c_{i}=1,c_{j}=1\);而我们可以选择\(4\)和\(6\),因为\(c_{i}=2,c_{j}=1\))
那么我们就可以根据倍数关系建图,进行拓扑排序,得到当\(b=i\)时\(c_{i}\)的取值范围(最大值和最小值)。如果有任何一个\(b=i\)时\(c_{i}\)的取值范围是空的话(即最小取值大于最大取值),意味着\(b=i\)时我们没法选择,此时也全部输出\(No\)。
否则我们就判断\(c_{i}\)是否在\(b_{i}\)时的取值范围内部,输出\(Yes\)或\(No\)。
时间复杂度为\(O(n\log n)\)。
#include<bits/stdc++.h>
#define debug(...) std::cerr<<#__VA_ARGS__<<" : "<<__VA_ARGS__<<std::endl
const int maxn=600005;
int n,m;
int a[maxn],pw[maxn];
int mx[maxn],in[maxn];
int mn[maxn],rin[maxn];
std::vector<int> vec[maxn],g[maxn],rg[maxn];
int main() {
scanf("%d%d",&n,&m);
for(int i=1,num;i<=n;i++) {
scanf("%d",&a[i]);
pw[i]=1,num=a[i];
while(num%2==0) num/=2,pw[i]+=pw[i];
vec[a[i]/pw[i]].push_back(pw[i]);
}
for(int i=1;i<=m+m;i+=2) {
if(vec[i].empty()) {
for(int i=1;i<=n;i++) printf("No\n");
exit(0);
}
std::sort(vec[i].begin(),vec[i].end());
}
for(int i=1;i<=m+m;i++) {
for(int j=i+i;j<=m+m;j+=i) {
//从i连向一个通往j的边
if(i%2==0||j%2==0) continue;//下标只能是奇数
g[i].push_back(j); in[j]++;
rg[j].push_back(i); rin[i]++;
}
}
std::queue<int> q;
for(int i=1;i<=m+m;i+=2) {
mx[i]=vec[i].back();
if(!in[i]) q.push(i);
}
while(!q.empty()) {
int pos=q.front(); q.pop();
for(auto to : g[pos]) {
int p=std::lower_bound(vec[to].begin(),vec[to].end(),mx[pos])-vec[to].begin()-1;
if(p>=0) {
mx[to]=std::min(mx[to],vec[to][p]);
} else {
mx[to]=-1;//impossible
}
in[to]--;
if(!in[to]) q.push(to);
}
}
for(int i=1;i<=m+m;i+=2) {
mn[i]=vec[i][0];
if(!rin[i]) q.push(i);
}
while(!q.empty()) {
int pos=q.front(); q.pop();
for(auto to : rg[pos]) {
int p=std::upper_bound(vec[to].begin(),vec[to].end(),mn[pos])-vec[to].begin();
if(p>=vec[to].size()) {
mn[to]=1e9;
} else {
mn[to]=std::max(mn[to],vec[to][p]);
}
rin[to]--;
if(!rin[to]) q.push(to);
}
}
for(int i=1;i<=m+m;i+=2) {
if(mn[i]==1e9||mx[i]==-1) {
for(int j=1;j<=n;j++) printf("No\n");
exit(0);
}
}
for(int i=1;i<=n;i++) {
int ind=a[i]/pw[i];
if(mn[ind]<=pw[i]&&pw[i]<=mx[ind]) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
}
/*
6 6
4 5 12 7 9 11
*/
浙公网安备 33010602011771号