Description
维护一个序列,资瓷
1:将A[l]~A[r]中的每一个A[x]变为(x-l+1)*a mod b
2:询问A[l]~A[r]的和
n<=1e9,m<=5*1e4
Solution
考虑将一次赋值看做一个颜色段,然后同一个颜色段里面的和我们可以用类欧来计算。
用线段树维护是log^2的,但我们其实有一种更加优美的写法
我们可以用一棵平衡树来维护每一个颜色端,这样子复杂度就变成了一个log了。
但是比线段树难写多了QwQ
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef unsigned long long ll;
int read() {
char ch;
for(ch=getchar();ch<'0'||ch>'9';ch=getchar());
int x=ch-'0';
for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x;
}
void write(ll x) {
if (!x) {puts("0");return;}
char ch[20];int tot=0;
for(;x;x/=10) ch[++tot]=x%10+'0';
fd(i,tot,1) putchar(ch[i]);
puts("");
}
const int N=2*1e5+5;
ll Sum[N],Key[N];
int L[N],R[N],St[N],A[N],B[N],f[N],t[N][2],tot;
int n,q,a,b,opt,l,r,root;
ll sum(ll n) {return (n&1)?((n+1)/2*n):(n/2*(n+1));}
ll solve(ll a,ll b,ll c,ll n) {
ll m=(a*n+b)/c;
if (!a) return b/c*n;
if (!m) return 0;
if (a<c&&b<c) return n*m-solve(c,c-b-1,a,m-1);
ll res=0;
if (a>=c) res+=a/c*sum(n),a%=c;
if (b>=c) res+=b/c*(n+1),b%=c;
return res+solve(a,b,c,n);
}
ll calc(int n,int a,int b) {
ll res=(ll)a*sum(n);
return res-(ll)b*solve(a,0,b,n);
}
int son(int x) {return t[f[x]][1]==x;}
void updata(int x) {Sum[x]=Sum[t[x][0]]+Sum[t[x][1]]+Key[x];}
void rotate(int x) {
int y=f[x],z=son(x);
if (f[y]) t[f[y]][son(y)]=x;
if (t[x][1-z]) f[t[x][1-z]]=y;
f[x]=f[y];f[y]=x;
t[y][z]=t[x][1-z];t[x][1-z]=y;
updata(y);updata(x);
}
void splay(int x,int y) {
while (f[x]!=y) {
if (f[f[x]]!=y)
if (son(x)==son(f[x])) rotate(f[x]);
else rotate(x);
rotate(x);
}
if (!y) root=x;
}
int find(int x,int k) {
if (L[x]<=k&&k<=R[x]) return x;
if (R[x]<k) return find(t[x][1],k);
else return find(t[x][0],k);
}
void modify(int x) {
Key[x]=calc(R[x]-St[x]+1,A[x],B[x])-calc(L[x]-St[x],A[x],B[x]);
if (f[x]) splay(x,0);
}
void insert(int &x,int now,int fa) {
if (!x) {
x=now;
f[x]=fa;
splay(x,0);
return;
}
if (R[x]<L[now]) insert(t[x][1],now,x);
else insert(t[x][0],now,x);
}
int main() {
n=read();q=read();
L[root=tot=1]=1;R[tot]=n;B[tot]=1000000;St[tot]=1;
for(;q;q--) {
opt=read();l=read();r=read();
if (opt==1) {
a=read();b=read();
int posl=find(root,l);splay(posl,0);
int posr=find(root,r);
if (posl!=posr) {
splay(posr,posl);
f[t[posr][0]]=0;t[posr][0]=0;
if (R[posl]+1!=L[posr]) {
A[++tot]=a;B[tot]=b;St[tot]=l;
L[tot]=R[posl]+1;R[tot]=L[posr]-1;
modify(tot);
insert(root,tot,0);
}
if (l==L[posl]) {
A[posl]=a;B[posl]=b;St[posl]=l;
modify(posl);
} else {
A[++tot]=a;B[tot]=b;St[tot]=l;
L[tot]=l;R[tot]=R[posl];
R[posl]=l-1;
modify(tot);modify(posl);
insert(root,tot,0);
}
if (r==R[posr]) {
A[posr]=a;B[posr]=b;St[posr]=l;
modify(posr);
} else {
A[++tot]=a;B[tot]=b;St[tot]=l;
L[tot]=L[posr];R[tot]=r;
L[posr]=r+1;
modify(tot);modify(posr);
insert(root,tot,0);
}
} else {
if (l==L[posl]&&r==R[posl]) {
A[posl]=a;B[posl]=b;St[posl]=l;
modify(posl);
} else {
if (l!=L[posl]) {
A[++tot]=A[posl];B[tot]=B[posl];St[tot]=St[posl];
L[tot]=L[posl];R[tot]=l-1;
L[posl]=l;
modify(tot);modify(posl);
insert(root,tot,0);
}
if (r!=R[posl]) {
A[++tot]=A[posl];B[tot]=B[posl];St[tot]=St[posl];
L[tot]=r+1;R[tot]=R[posl];
R[posl]=r;
modify(tot);modify(posl);
insert(root,tot,0);
}
A[posl]=a;B[posl]=b;St[posl]=l;
modify(posl);
}
}
}
if (opt==2) {
int posl=find(root,l);splay(posl,0);
int posr=find(root,r);
ll ans=0;
if (posl!=posr) {
splay(posr,posl);
ans=Sum[t[posr][0]];
ans+=calc(R[posl]-St[posl]+1,A[posl],B[posl])-
calc(l-St[posl],A[posl],B[posl]);
ans+=calc(r-St[posr]+1,A[posr],B[posr])
-calc(L[posr]-St[posr],A[posr],B[posr]);
} else ans=calc(r-St[posl]+1,A[posl],B[posl])-
calc(l-St[posl],A[posl],B[posl]);
write(ans);
}
}
}