题目大意
给定一个长度为 \(n\) 的序列 \(a\) 和一个数字 \(x\)。
你需要在序列 \(a\) 后面加上一些元素,然后对整个序列重新排序,使得对于 \([1,n]\) 内的任意奇数 \(i\) 都有 \(a_i\cdot x=a_{i+1}\)。
数据范围:\(n\le 2\times10^5,\sum n\le 2\times 10^5,2\le x\le10^6,1\le a_i\le 10^9\)。
题目解析
考虑贪心。
首先把整个序列按升序排序。
然后从头到尾扫一次,如果 \(a_i\cdot x\) 存在,那么就把它删掉,否则就在序列里加入这个数字(也就是答案加一)。
我们发现需要使用哈希或者是平衡树来维护,这样就可以做到 \(O\left(n\right)\) 或者是 \(O\left(n\log n\right)\)。
这里用 set
来维护。
我们发现 \(x\le 10^6,a_i\le 10^9\),也就是说 \(a_i\cdot x\le 10^{15}\),会爆 int
,所以一定要开 long long
。听说 Div 2 一堆人因为没开 FST 了。
代码:
struct JTZ{
ll x; int num;
bool operator < (const JTZ x) const {
if(this->x==x.x) return this->num < x.num;
return this->x < x.x;
}
};
set<JTZ> s,E;
int n,flag[maxn];
ll x,a[maxn];
void work(){
s=E; n=read(); x=read(); int i,ans=0;
for(i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1);
for(i=1;i<=n;i++) s.insert((JTZ){a[i],i}),flag[i]=1;
for(i=1;i<=n;i++) if(flag[i]){
flag[i]=0;
s.erase((JTZ){a[i],i});
set<JTZ>::iterator tmp=s.lower_bound((JTZ){a[i]*x,i});
if((*tmp).x==a[i]*x) flag[(*tmp).num]=0,s.erase(tmp);
else ans++;
} print(ans),pc('\n'); return;
}