题目传送门
题意
- 非负整数序列,支持 区间和查询 和 区间所有某数倍数除以其。
Sol
真就卡常 最后改成指针才行
考虑一个数的因数个数不超过 (2sqrt{a_i}),不妨对每个因数开链表,记录其倍数位置。
考虑每个数最多能被操作 (log{a_i}) 次,我们每次暴力修改链表就行了。
区间和可以写个 BIT,毕竟常数小。(
总复杂度 (O(nsqrt{a_i}+nlog nlog {a_i}))。
// wish to get better qwq
#include<bits/stdc++.h>
#define re register int
#define pb push_back
using namespace std;
typedef long long ll;
template <typename T> void rd(T &x){
int fl=1;x=0;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') fl=-fl;
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
x*=fl;
}
void wr(ll x){
if(x<0) x=-x,putchar('-');
if(x<10) putchar(x+'0');
if(x>9) wr(x/10),putchar(x%10+'0');
}
// ---------- IO ---------- //
const int N=5e5+5;
int n,m,a[N];
vector<int> f[N],fa[N];
ll sum[N],ans;
inline int lowbit(int x){return x&(-x);}
inline void add(int x,ll k){
while(x<=n) sum[x]+=k,x+=lowbit(x);
}
inline ll query(int x){
ll s=0;
while(x) s+=sum[x],x-=lowbit(x);
return s;
}
// ---------- BIT ---------- //
inline int found(int pos,int x){
if(x>=fa[pos].size()) return x;
return fa[pos][x]==x?fa[pos][x]:fa[pos][x]=found(pos,fa[pos][x]);
}
// ---------- DSU ---------- //
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
rd(n);rd(m);
for(re i=1;i<=n;++i){
rd(a[i]);add(i,a[i]);
for(re j=1;j*j<=a[i];++j)
if(a[i]%j==0){
f[j].pb(i);fa[j].pb(fa[j].size());
if(j*j!=a[i]) f[a[i]/j].pb(i),fa[a[i]/j].pb(fa[a[i]/j].size());
}
}
int op,l,r,x;
for(re i=1;i<=m;++i){
rd(op);rd(l);rd(r);l^=ans;r^=ans;
if(op==1){
rd(x);x^=ans;
if(x==1) continue;
int st=lower_bound(f[x].begin(),f[x].end(),l)-f[x].begin();
for(re j=found(x,st);j<f[x].size()&&f[x][j]<=r;j=found(x,j+1)){
if(a[f[x][j]]%x==0) add(f[x][j],a[f[x][j]]/x-a[f[x][j]]),a[f[x][j]]/=x;
if(a[f[x][j]]%x!=0) fa[x][j]=found(x,j+1);
}
}
else wr(ans=query(r)-query(l-1)),puts("");
}
return 0;
}
// ---------- Main ---------- //
然后你就发现被卡常了
预计得分 (62)。
我们考虑卡常。(
把数组全部改成指针即可。(
注意细节,不要 (<=) 写成 (<)。(
会 RE 飞。(
// wish to get better qwq
#include<bits/stdc++.h>
#define re register int
#define pb push_back
#define lb lower_bound
#define ub upper_bound
using namespace std;
typedef long long ll;
template <typename T> void rd(T &x){
int fl=1;x=0;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') fl=-fl;
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
x*=fl;
}
void wr(ll x){
if(x<0) x=-x,putchar('-');
if(x<10) putchar(x+'0');
if(x>9) wr(x/10),putchar(x%10+'0');
}
// ---------- IO ---------- //
const int N=5e5+5;
int n,m,a[N],cnt[N],maxn,*p[N],node[N*505],*tp=node;
ll sum[N],ans;
inline int ma(int x,int y){return x<y?y:x;}
inline void add(int x,ll k){
while(x<=n) sum[x]+=k,x+=x&(-x);
}
inline ll query(int x){
ll s=0;
while(x) s+=sum[x],x^=x&(-x);
return s;
}
// ---------- BIT ---------- //
struct DSU{
int *fa;
inline void init(int n){for(re i=0;i<n;++i) fa[i]=i;}
inline int found(int x){return fa[x]==x?x:fa[x]=found(fa[x]);}
}nxt[N];
// ---------- DSU ---------- //
inline void modify(int l,int r,int x){
l=lb(p[x],p[x]+cnt[x],l)-p[x];
r=ub(p[x],p[x]+cnt[x],r)-p[x]-1;
if(l>r) return ;
for(re nw=nxt[x].found(l);nw<=r;nw=nxt[x].found(nw+1)){
int t=p[x][nw];
if(a[t]%x==0) add(t,a[t]/x-a[t]),a[t]/=x;
if(nw>=r) break;
if(a[t]%x) nxt[x].fa[nw]=nxt[x].found(nw+1);
}
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
rd(n);rd(m);
for(re i=1;i<=n;++i){
rd(a[i]);add(i,a[i]);
cnt[a[i]]++;maxn=ma(maxn,a[i]);
}
for(re i=1;i<=maxn;++i)
for(re j=i+i;j<=maxn;j+=i) cnt[i]+=cnt[j];
for(re i=1;i<=maxn+1;++i)
if(cnt[i]){
p[i]=tp;tp+=cnt[i];
nxt[i].fa=tp;nxt[i].init(cnt[i]);
tp+=cnt[i];cnt[i]=0;
}
for(re i=1;i<=n;++i){
for(re j=1;j*j<=a[i];++j)
if(a[i]%j==0){
p[j][cnt[j]++]=i;
if(j*j!=a[i]) p[a[i]/j][cnt[a[i]/j]++]=i;
}
}
int op,l,r,x;
for(re i=1;i<=m;++i){
rd(op);rd(l);rd(r);l^=ans;r^=ans;
if(op==1){
rd(x);x^=ans;
if(x==1) continue;
modify(l,r,x);
}
else wr(ans=query(r)-query(l-1)),puts("");
}
return 0;
}
// ---------- Main ---------- //