我永远喜欢珂朵莉~
Posted StaroForgin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我永远喜欢珂朵莉~相关的知识,希望对你有一定的参考价值。
我永远喜欢珂朵莉~
题解
首先,除去
x
=
1
x=1
x=1的情况,我们的一个数最多进行
l
o
g
a
i
log\\,a_{i}
logai次除法,所以事实上我们是可以对每个数暴力进行除法的,通过树状数组来维护区间和。
所以对于数进行修改方面我们的时间复杂度是
O
(
n
log
2
n
)
O\\left(n\\log^2\\,n\\right)
O(nlog2n)。
但真正的问题在于我们如何快速地找到我们需要进行修改的数。
由于一个数在
5
×
1
0
5
5\\times 10^5
5×105以内,一个数最多会有
300
300
300个约数左右,我们不妨对于每个数建一棵
T
r
e
a
p
Treap
Treap,表示为这个数倍数的位置有哪些。放心,
1.22
G
B
1.22GB
1.22GB的空间再怎么也不会MLE
我们每次操作就直接从
x
x
x对应的
T
r
e
a
p
Treap
Treap中分裂出区间
[
l
,
r
]
[l,r]
[l,r],将里面的数除以
x
x
x。
但当我们除去这个
x
x
x后可能影响
a
i
a_{i}
ai的其它约数,我们不可能一个一个地进行更改,不如我们改一下原来的定义,改为可能为这个数倍数的数。
因为我们只有除法,所以一个数的约数集合只会不断减少,不会增加,所以我们就不用管加点,只在每次调用这个区间时将不符合条件的点去掉即可。
同理,我们在操作后也会有相当一部分点变得不能并入原树,我们将可以并入的点拿出来建一棵新树后再合并进去就行了。
很明显,这种情况下每个数没进行一次操作,至少减少一个约数的位置,所以这部分时
O
(
n
d
)
O\\left(nd\\right)
O(nd)的,
d
d
d表示原数的约数个数。
总时间复杂度 O ( n ( d + log 2 n ) + m l o g n ) O\\left(n(d+\\log^2\\,n)+mlog\\,n\\right) O(n(d+log2n)+mlogn)。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXM 500005
#define MAXN 100005
#define MAXT 20000005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mo=1e9+7;
const int inv2=499122177;
const int jzm=2333;
const int zero=10000;
const int lim=500000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,m,root[MAXM],val[MAXN],sta[MAXN],stak,tim;LL tr[MAXN];
vector<int>vec[MAXM];
void insert(int pos,int aw){while(pos<=n)tr[pos]+=1ll*aw,pos+=lowbit(pos);}
LL query(int pos){LL res=0;while(pos)res+=tr[pos],pos-=lowbit(pos);return res;}
struct ming{
int lson,rson,val,siz,rnd;
ming(){lson=rson=val=siz=rnd=0;}
};
class FHQ_Treap{
private:
ming tr[MAXT];int tot;
int newnode(int w){
int rt=++tot;tr[rt].siz=1;tr[rt].val=w;
tr[rt].rnd=rand();return rt;
}
void pushup(int rt){tr[rt].siz=tr[tr[rt].lson].siz+tr[tr[rt].rson].siz+1;}
void split(int now,int k,int &x,int &y){
if(!now){x=y=0;return ;}
if(tr[now].val>k)
y=now,split(tr[now].lson,k,x,tr[now].lson),pushup(y);
else x=now,split(tr[now].rson,k,tr[now].rson,y),pushup(x);
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(tr[x].rnd<tr[y].rnd){
tr[x].rson=merge(tr[x].rson,y);
pushup(x);return x;
}
tr[y].lson=merge(x,tr[y].lson);
pushup(y);return y;
}
void search(int rt){
if(tr[rt].lson)search(tr[rt].lson);
sta[++stak]=tr[rt].val;
if(tr[rt].rson)search(tr[rt].rson);
}
public:
int build(int l,int r){
int mid=l+r>>1,rt=newnode(sta[mid]);
if(l<mid)tr[rt].lson=build(l,mid-1);
if(r>mid)tr[rt].rson=build(mid+1,r);
pushup(mid);return rt;
}
void modify(int l,int r,int aw){
if(aw<2||!root[aw])return ;int x1,y1,x2,y2;split(root[aw],r,x1,y1);
split(x1,l-1,x2,y2);if(!y2){root[aw]=merge(x2,y1);return ;}
stak=0;search(y2);int tt=0;
for(int i=1;i<=stak;i++)if(val[sta[i]]%aw==0){
insert(sta[i],-val[sta[i]]),
val[sta[i]]/=aw,insert(sta[i],val[sta[i]]);
if(val[sta[i]]%aw==0)sta[++tt]=sta[i];
}
if(tt)root[aw]=merge(x2,merge(build(1,tt),y1));
else root[aw]=merge(x2,y1);
}
}T;
signed main(){
read(n);read(m);
for(int i=1;i<=n;i++){
read(val[i]),insert(i,val[i]);
for(int j=2;1ll*j*j<=val[i];j++){
if(val[i]%j)continue;vec[j].pb(i);
if(val[i]/j!=j)vec[val[i]/j].pb(i);
}
vec[val[i]].pb(i);
}
for(int i=2;i<=lim;i++){
stak=0;for(int j=0;j<vec[i].size();j++)sta[++stak]=vec[i][j];
if(!stak)continue;root[i]=T.build(1,stak);
}
for(int i=1;i<=m;i++){
int opt,l,r,x;read(opt);tim=i;
if(opt==1)read(l),read(r),read(x),T.modify(l,r,x);
if(opt==2)read(l),read(r),printf("%lld\\n",query(r)-query(l-1));
}
return 0;
}
谢谢!!!
以上是关于我永远喜欢珂朵莉~的主要内容,如果未能解决你的问题,请参考以下文章
CF896C Willem, Chtholly and Seniorious 珂朵莉树