【WinterCamp 2013】阿凡达

来源:互联网 发布:阿里巴巴北京总部 知乎 编辑:程序博客网 时间:2024/06/06 02:24

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);        }    }}
原创粉丝点击