mxqz平衡树
  • 板块P5142 区间方差
  • 楼主Imiya
  • 当前回复2
  • 已保存回复2
  • 发布时间2022/8/10 23:11
  • 上次更新2023/10/27 16:01:37
查看原帖
mxqz平衡树
455558
Imiya楼主2022/8/10 23:11

WA on 8,9 qwq,感觉改模的地方都模了

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
#define int long long
inline int read(){
    int i=getchar(),r=0;
    while(i<'0'||i>'9')i=getchar();
    while(i>='0'&&i<='9')r=(r<<1)+(r<<3)+(i^48),i=getchar();
    return r;
}
const int N=100100,P=1e9+7;
int ls[N],rs[N],wei[N],siz[N];
int val[N],sum[N],sum2[N],laz[N];
int cnt,rt;
inline void push_down(int nd){
    if(!laz[nd])return;
    val[nd]=laz[nd]%P;
    sum2[nd]=laz[nd]*siz[nd]%P*laz[nd]%P;
    sum[nd]=laz[nd]*siz[nd]%P;
    if(ls[nd])laz[ls[nd]]=laz[nd];
    if(rs[nd])laz[rs[nd]]=laz[nd];
    laz[nd]=0;
}
inline void push_up(int nd){
    push_down(ls[nd]);
    push_down(rs[nd]);
    siz[nd]=siz[ls[nd]]+siz[rs[nd]]+1;
    sum[nd]=(sum[ls[nd]]+sum[rs[nd]]+val[nd])%P;
    sum2[nd]=(sum2[ls[nd]]+sum2[rs[nd]]+val[nd]*val[nd]%P)%P;
}
#define p1 first
#define p2 second
pair<int,int>split(int nd,int k){
    if(!nd)return{0,0};
    push_down(nd);
    if(siz[ls[nd]]+1<=k){
        pair<int,int>o=split(rs[nd],k-siz[ls[nd]]-1);
        rs[nd]=o.p1;push_up(nd);
        return{nd,o.p2};
    }
    else{
        pair<int,int>o=split(ls[nd],k);
        ls[nd]=o.p2;push_up(nd);
        return{o.p1,nd};
    }
}
int merge(int u,int v){
    if(!u||!v)return u|v;
    push_down(u);
    push_down(v);
    if(wei[u]<wei[v]){
        rs[u]=merge(rs[u],v);
        push_up(u);
        return u;
    }
    else{
        ls[v]=merge(u,ls[v]);
        push_up(v);
        return v;
    }
}
inline int New(int k){
    siz[++cnt]=1;
    val[cnt]=sum[cnt]=k;
    sum2[cnt]=k*k%P;
    wei[cnt]=rand();
    return cnt;
}
inline void insert(int p,int k){
    pair<int,int>o=split(rt,p-1);
    rt=merge(o.p1,merge(New(k),o.p2));
}
inline void add(int l,int r,int k){
    pair<int,int>o=split(rt,r);
    pair<int,int>p=split(o.p1,l-1);
    laz[p.p2]=k;
    rt=merge(merge(p.p1,p.p2),o.p2);
}
inline int get_sum(int l,int r){
    pair<int,int>o=split(rt,r);
    pair<int,int>p=split(o.p1,l-1);
    push_down(p.p2);
    int res=sum[p.p2];
    rt=merge(merge(p.p1,p.p2),o.p2);
    return res;
}
inline int get_sum2(int l,int r){
    pair<int,int>o=split(rt,r);
    pair<int,int>p=split(o.p1,l-1);
    push_down(p.p2);
    int res=sum2[p.p2];
    rt=merge(merge(p.p1,p.p2),o.p2);
    return res;
}
pair<int,int>exgcd(int x,int y,pair<int,int>a,pair<int,int>b){
    if(x<y)swap(x,y),swap(a,b);
    if(!y)return a;
    return exgcd(y,x%y,b,{((a.p1-x/y*b.p1)%P+P)%P,((a.p2-x/y*b.p2)%P+P)%P});
}
signed main(){
    // freopen("read.in","r",stdin);
    srand(time(0));
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++)insert(i,read());
    while(m--){
        int cmd=read(),l=read(),r=read();
        int a=get_sum(l,r)%P;
        int b=get_sum2(l,r)%P;
        int c=r-l+1;
        if(cmd==1)add(l,l,r);
        else{
            b=((b*c%P-a*a%P)%P+P)%P;
            c=c*c%P;
            int ans=exgcd(c,P,{1,0},{0,1}).p1;
            if(ans<0)ans+=(-ans)/P*P+P;
            printf("%lld\n",ans%P*b%P);
        }
    }
    return 0;
}
2022/8/10 23:11
加载中...