题目链接:https://loj.ac/p/576
给出一个长度为n的序列a,还有一个未知序列b,你每次可以花费gcdri=lai的代价得到∑ri=lbi的值。
每次修改a中的一个数,求得到b中所有数字需要花费的最小权值。
1≤n,q≤105,1≤ai≤109
因为有一个信息上的问题,有限的信息对应的结果肯定不能超过信息的数量。所以我们需要知道n个数字那么我们就至少需要询问n次。
然后考虑si=∑ij=1bj,那么我们每次得到的将是一个sr−sl−1,我们可以通过一个[l,r]和[l′,r]的询问得到[l,l′−1](反过来同理)。也就是一些端点相互连接相互覆盖的区间我们可以把它们转换为端点相同但是没有相互覆盖的区间。
然后我们目标是所有端点都得在里面,加上相互连接这个限制,看上去就很像最小生成树。相当于有点[0,n],我们连接l,r的代价是gcdri=l+1ai,求最小生成树。
然后显然的我们肯定是找一个k,然后0∼k向n连边,k+1∼n向0连边,主要是找到这个k,这个k就是第一个满足gcdki=1ai≤gcdni=kai的位置。
然后因为前后缀gcd都最多变化log次,我们可以考虑求出这些位置。
考虑在线段树上二分出这些位置,看上去是log3的,实际上假设L∼mid中没有答案,那么此时这个前缀的gcd依旧等于val,所以不需要管前面的东西,到一个位置的时候判这个区间的值是不是val的倍数就好了。
时间复杂度:O(nlog2n)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define mp(x,y) make_pair(x,y)
#define ll long long
using namespace std;
const ll N=1e5+10;
ll n,q,a[N],w[N<<2];
vector<pair<ll,ll> > pre,suf;
void Change(ll x,ll L,ll R,ll pos,ll val){
if(L==R){w[x]=val;return;}
ll mid=(L+R)>>1;
if(pos<=mid)Change(x*2,L,mid,pos,val);
else Change(x*2+1,mid+1,R,pos,val);
w[x]=__gcd(w[x*2],w[x*2+1]);return;
}
ll AskP(ll x,ll L,ll R,ll pos,ll &val){
if(w[x]%val==0)return n;
if(L==R){val=__gcd(val,w[x]);return L;}
ll mid=(L+R)>>1;
if(pos>mid)return AskP(x*2+1,mid+1,R,pos,val);
ll k=AskP(x*2,L,mid,pos,val);
if(k==n)return AskP(x*2+1,mid+1,R,pos,val);
return k;
}
ll AskS(ll x,ll L,ll R,ll pos,ll &val){
if(w[x]%val==0)return 0;
if(L==R){val=__gcd(val,w[x]);return L;}
ll mid=(L+R)>>1;
if(pos<=mid)return AskS(x*2,L,mid,pos,val);
ll k=AskS(x*2+1,mid+1,R,pos,val);
if(!k)return AskS(x*2,L,mid,pos,val);
return k;
}
ll Ask(ll x,ll L,ll R,ll l,ll r){
if(L==l&&R==r)return w[x];
int mid=(L+R)>>1;
if(r<=mid)return Ask(x*2,L,mid,l,r);
if(l>mid)return Ask(x*2+1,mid+1,R,l,r);
return __gcd(Ask(x*2,L,mid,l,mid),Ask(x*2+1,mid+1,R,mid+1,r));
}
signed main()
{
scanf("%lld%lld",&n,&q);ll d=0;n++;
for(ll i=1;i<n;i++)
scanf("%lld",&a[i]),Change(1,0,n,i,a[i]);
Change(1,0,n,0,1);Change(1,0,n,n,1);
while(q--){
ll p,x;pre.clear();suf.clear();
scanf("%lld%lld",&p,&x);
Change(1,0,n,p,x);a[p]=x;
ll val=a[1];x=1;
while(x<n){
pre.push_back(mp(x,val));
x=AskP(1,0,n,x+1,val);
}
x=n-1;val=a[n-1];
while(x){
suf.push_back(mp(x-1,val));
x=AskS(1,0,n,x-1,val);
}
ll p1=pre.size()-1,p2=suf.size()-1;
ll L=-1,R=n,ans=0;
while(1){
if(p2<0||pre[p1].second<suf[p2].second){
if(pre[p1].first<=L){
ans+=pre[p1].second*(R-L-1);
break;
}
ans+=pre[p1].second*(R-pre[p1].first);
R=pre[p1].first;p1--;
}
else{
if(suf[p2].first>=R){
ans+=suf[p2].second*(R-L-1);
break;
}
ans+=suf[p2].second*(suf[p2].first-L);
L=suf[p2].first;p2--;
}
}
printf("%lld\n",ans-Ask(1,0,n,1,n-1));
}
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2021-07-14 jzoj7175-[2021.07.14NOI模拟]种蘑菇(mushroom)【莫比乌斯反演,树形dp】
2021-07-14 P7726-天体探测仪(Astral Detector)【构造】