题解:P17846 回天
solution
首先刻画一下最优解的特征。定义只有一种数的可重集为单集,否则为双集。
首先发现它不可能由两个双集构成,原因是我们发现答案有一个下界为
如果我们枚举单集是由哪种数组成的显然复杂度太高,考虑剪掉一些不优解。具体地,我们发现单集的数只能选严格最大值与次大值,否则不优。考虑证明,假设去重后从大到小排完序后为
接下来只需考虑钦定单集元素之后的事情,相当于要求除它之外所有数的
时间复杂度
code
#include<bits/stdc++.h>
using namespace std;
const int N=1000000,V=1000000000;
int n,a[N],q;
struct SGT
{
int idx=1;
struct node
{
int lp,rp,l,r,sum,cnt;
}tree[N*20];
void update(int x,int qp,int op)
{
if(tree[x].l==tree[x].r)
{
tree[x].cnt+=op;
if(tree[x].cnt)
{
tree[x].sum=tree[x].l;
}
else
{
tree[x].sum=0;
}
return;
}
int mid=((tree[x].l+tree[x].r)>>1);
if(qp<=mid)
{
if(!tree[x].lp)
{
tree[x].lp=++idx;
tree[tree[x].lp]={0,0,tree[x].l,mid,0,0};
}
update(tree[x].lp,qp,op);
}
else
{
if(!tree[x].rp)
{
tree[x].rp=++idx;
tree[tree[x].rp]={0,0,mid+1,tree[x].r,0,0};
}
update(tree[x].rp,qp,op);
}
tree[x].sum=__gcd(tree[tree[x].lp].sum,tree[tree[x].rp].sum);
return;
}
int query(int x,int ql,int qr)
{
if(!x)
{
return 0;
}
if(ql<=tree[x].l&&tree[x].r<=qr)
{
return tree[x].sum;
}
int res=0,mid=((tree[x].l+tree[x].r)>>1);
if(ql<=mid)
{
res=__gcd(query(tree[x].lp,ql,qr),res);
}
if(qr>mid)
{
res=__gcd(query(tree[x].rp,ql,qr),res);
}
return res;
}
}S;
set<int> s;
unordered_map<int,int> mp;
int f(int x)
{
return __gcd(S.query(1,1,x-1),S.query(1,x+1,V))+x;
}
void solve()
{
if(s.size()==1)
{
cout<<2*(*s.rbegin())<<"\n";
return;
}
int h=(*s.rbegin());
int ans=f(h);
s.erase(h);
if(!s.empty())
{
ans=max(ans,f((*s.rbegin())));
}
s.insert(h);
cout<<ans<<"\n";
return;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
S.tree[1]={0,0,1,V,0};
for(int i=1;i<=n;i++)
{
cin>>a[i];
S.update(1,a[i],1);
mp[a[i]]++;
if(mp[a[i]]==1)
{
s.insert(a[i]);
}
}
solve();
cin>>q;
while(q--)
{
int x,y;
cin>>x>>y;
S.update(1,a[x],-1);
mp[a[x]]--;
if(mp[a[x]]==0)
{
s.erase(a[x]);
}
S.update(1,y,1);
a[x]=y;
mp[y]++;
if(mp[y]==1)
{
s.insert(y);
}
solve();
}
return 0;
}