# [洛谷P3987]我永远喜欢珂朵莉~

1. 给一个区间内所有$v_i$的倍数除以$v_i$。
2. 询问区间和。

C++ Code：

#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define reg register
using LoveLive=long long;
const int M=1e6+5,N=1e5+5;
LoveLive btr[M];
int n,m,a[N],opt[N],L[N],R[N],v[N],cnt=0,rt[M],nodes=0;
std::vector<int>V[1000005];std::stack<int>st;
struct node{
int ls,rs,r,v,sz;
}d[M<<6];
bool vis[M];
inline void add(int x,int d){for(;x<=M;x+=x&-x)btr[x]+=d;}
inline LoveLive ask(int x){reg LoveLive r=0;for(;x;x-=x&-x)r+=btr[x];return r;}
reg int c=getchar(),d=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
inline int merge(int x,int y){
if(!x||!y)return x|y;
if(d[x].r<d[y].r){
d[x].rs=merge(d[x].rs,y);
return x;
}
d[y].ls=merge(x,d[y].ls);
return y;
}
inline void split(int u,int k,int&x,int&y){
if(!u)return void(x=y=0);
if(d[u].v<=k)
split(d[x=u].rs,k,d[u].rs,y);else
split(d[y=u].ls,k,x,d[u].ls);
}
inline void Delete(int&rt,int x){
reg int a,b;
split(rt,x-1,rt,a);
split(a,x,a,b);
rt=merge(rt,b);
}
int build(int l,int r,int&i){
if(l>r)return 0;
reg int nw=++nodes,mid=l+r>>1;
d[nw]=(node){0,0,rand(),V[i][mid]};
d[nw].ls=build(l,mid-1,i);
d[nw].rs=build(mid+1,r,i);
return nw;
}
void dfs(int now,int&v){
if(!now)return;
dfs(d[now].ls,v),dfs(d[now].rs,v);
int&nw=a[d[now].v];
if(nw%v==0){
nw/=v;
}
if(nw%v)st.push(d[now].v);
}
int main(){
srand(time(0));
srand(rand());
for(reg int i=1;i<=m;++i){
}
//begin 寻找每个数的约数并将每个数的位置插入对应的平衡树
for(reg int i=1;i<=n;++i){
reg int&nw=a[i];
for(reg int j=1;j*j<=a[i];++j)
if(nw%j==0){
if(vis[j]&&j>1)V[j].push_back(i);
if(j*j<nw&&vis[nw/j])V[nw/j].push_back(i);
}
}
for(reg int i=2;i<M;++i)
if(V[i].size())rt[i]=build(0,V[i].size()-1,i);
//end
//begin 查询及修改
for(reg int i=1;i<=m;++i)
if(opt[i]==1){
if(v[i]>1){
reg int&nw=rt[v[i]],x,y;
split(nw,L[i]-1,nw,x);
split(x,R[i],x,y);
dfs(x,v[i]);
nw=merge(merge(nw,x),y);
while(!st.empty()){
reg int p=st.top();
st.pop();
split(nw,p-1,nw,x);
split(x,p,x,y);
nw=merge(nw,y);
}
}
}