zoukankan      html  css  js  c++  java
  • LibreOJ β Round #2 E. 数论只会 GCD

    传送门

    题解

    题解里面说得很清楚了。

    大约就是单独考虑每个数的贡献,然后看一下每个序列里有多少区间是没有这个数的,乘起来就好了。

    为了处理修改我们需要每个值建一棵线段树来搞,但是窝zz了,写了线段树套线段树,比正解多一个log。

    一开始想着不调map、set,然后发现特别难写。最后还是调了map……

    比赛的时候挂了0没有逆元的坑啊!

    #include<map>
    #include<cstdio>
    #include<algorithm>
    #define pii pair
    #define mpii make_pair
    #define MN 410000
    using namespace std;
    int read_p,read_ca,read_f;
    inline int read(){
        read_p=0;read_ca=getchar();read_f=1;
        while(read_ca<'0'||read_ca>'9') {if (read_ca=='-') read_f=-1;read_ca=getchar();}
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p*read_f;
    }
    const int MOD=19260817;
    struct na{int p,*st;}Y[MN<<1];
    bool operator < (na a,na b){return a.p<b.p;}
    inline void M(int &x){while(x>=MOD)x-=MOD;while(x<0)x+=MOD;}
    int n,m,L[MN],a[MN],ro[MN],RO[MN*40],ls[MN*40],rs[MN*40],LS[MN*100],RS[MN*100],S[MN*100],NUM,x[MN],y[MN],z[MN],T=0,num=0,_num=0,mmh[MN],MMH=1,t[MN],w[MN],ze[MN];
    void ADD(int &p,int l,int r,int pos,int v){
        if (!p) p=++_num;S[p]+=v;
        if (l==r) return;
        int mid=l+r>>1;
        if (pos<=mid) ADD(LS[p],l,mid,pos,v);else ADD(RS[p],mid+1,r,pos,v);
    }
    void add(int &p,int l,int r,int pos,int x,int v){
        if (!p) p=++num;ADD(RO[p],1,T,x,v);
        if (l==r) return;
        int mid=l+r>>1;
        if (pos<=mid) add(ls[p],l,mid,pos,x,v);else add(rs[p],mid+1,r,pos,x,v);
    }
    int ASK(int p,int l,int r,int k){
        if (!p) return 0;
        if (l==r) return S[p];
        int mid=l+r>>1;
        return k<=mid?ASK(LS[p],l,mid,k):ASK(RS[p],mid+1,r,k);
    }
    int p_ask(int p,int l,int r,int pos,int x){
        if (ASK(RO[p],1,T,x)==0) return -1;
        if (pos<=l) return -1;
        if (l==r) return l;
        int mid=l+r>>1;
        int w=p_ask(rs[p],mid+1,r,pos,x);
        if (w!=-1) return w;
        return p_ask(ls[p],l,mid,pos,x);
    }
    int s_ask(int p,int l,int r,int pos,int x){
        if (ASK(RO[p],1,T,x)==0) return -1;
        if (pos>=r) return -1;
        if (l==r) return l;
        int mid=l+r>>1;
        int w=s_ask(ls[p],l,mid,pos,x);
        if (w!=-1) return w;
        return s_ask(rs[p],mid+1,r,pos,x);
    }
    inline int mi(int x,int y){
        int mmh=1;
        while (y){
            if (y&1) mmh=1LL*mmh*x%MOD;
            x=1LL*x*x%MOD;y>>=1;
        }
        return mmh;
    }
    map<pii<int,int>,int> ma;
    map<pii<int,int>,int>::iterator it;
    inline void del(int x,int v){
        if(!ze[v])M(MMH+=mmh[v]);
        if (ma.find(mpii(x,v))==ma.end()) ma[mpii(x,v)]=1LL*(L[x]-L[x-1])*(L[x]-L[x-1]+1)/2%MOD;
        if (!ma[mpii(x,v)]) ze[v]--;else mmh[v]=1LL*mmh[v]*mi(ma[mpii(x,v)],MOD-2)%MOD;
    }
    inline void add(int x,int v){if (!ma[mpii(x,v)]) ze[v]++;else mmh[v]=1LL*mmh[v]*ma[mpii(x,v)]%MOD;if(!ze[v])M(MMH-=mmh[v]);}
    int main(){
        n=read();m=read();
        for (int i=1;i<=n;i++) L[i]=L[i-1]+read();
        for (int i=1;i<=n;i++){
            for (int j=L[i-1];j<L[i];j++) Y[++NUM].p=a[j]=read(),Y[NUM].st=&a[j];
            MMH=1LL*(L[i]-L[i-1])*(L[i]-L[i-1]+1)/2%MOD*MMH%MOD;
        }
        for (int i=1;i<=m;i++) x[i]=read(),y[i]=read(),Y[++NUM].p=z[i]=read(),Y[NUM].st=&z[i];
        sort(Y+1,Y+1+NUM);
        for (int i=1;i<=NUM;i++) T+=i==1||Y[i].p!=Y[i-1].p,*Y[i].st=T;
        for (int i=1;i<=T;i++) mmh[i]=MMH,ze[i]=0;
        MMH=1LL*MMH*T%MOD;
        for (int i=1;i<=n;i++)
        for (int j=L[i-1];j<L[i];j++)add(ro[i],1,L[i]-L[i-1],j-L[i-1]+1,a[j],1);
        
        
        for (int i=1;i<=n;i++){
            for (int j=L[i-1];j<L[i];j++)
            if (!t[a[j]]) w[j]=(1LL*(j-L[i-1]+1)*(j-L[i-1])>>1)%MOD,t[a[j]]=j+1;else w[j]=((1LL*(j+1-t[a[j]])*(j-t[a[j]])>>1)+w[t[a[j]]-1])%MOD,t[a[j]]=j+1;
            
            int s=mi(1LL*(L[i]-L[i-1])*(L[i]-L[i-1]+1)/2%MOD,MOD-2);
            for (int j=L[i]-1;j>=L[i-1];j--) if (t[a[j]]){
                M(w[j]+=1LL*(L[i]-t[a[j]]+1)*(L[i]-t[a[j]])/2%MOD);
                mmh[a[j]]=1LL*mmh[a[j]]*s%MOD;
                if (!w[j]) ze[a[j]]++;else mmh[a[j]]=1LL*mmh[a[j]]*w[j]%MOD;
                ma[mpii(i,a[j])]=w[j];
                t[a[j]]=0;
            }
        }
        
        for (int i=1;i<=T;i++) if (!ze[i]) M(MMH-=mmh[i]);
        printf("%d
    ",MMH);
        for (int i=1;i<=m;i++){
            int pos=L[x[i]-1]+y[i]-1;
            del(x[i],a[pos]);del(x[i],z[i]);
            
            int l=p_ask(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],a[pos]),r=s_ask(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],a[pos]);
            if (l==-1) l=0;if (r==-1) r=L[x[i]]-L[x[i]-1]+1;
            it=ma.find(mpii(x[i],a[pos]));
            M(it->second+=1LL*(r-y[i])*(y[i]-l)%MOD);
            
            l=p_ask(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],z[i]),r=s_ask(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],z[i]);
            if (l==-1) l=0;if (r==-1) r=L[x[i]]-L[x[i]-1]+1;
            it=ma.find(mpii(x[i],z[i]));
            M(it->second-=1LL*(r-y[i])*(y[i]-l)%MOD);
            
            
            add(x[i],a[pos]);add(x[i],z[i]);
            
            add(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],a[pos],-1);
            add(ro[x[i]],1,L[x[i]]-L[x[i]-1],y[i],z[i],1);a[pos]=z[i];
            printf("%d
    ",MMH);
        }
    }
    View Code
  • 相关阅读:
    算法--有序矩阵查找指定数
    算法--三色排序(经典的荷兰国旗问题)
    算法--两个有序数组合并
    Latex 学习之旅
    Windows 下安装 tensorflow & keras & opencv 的避坑指南!
    platform 模块
    `__pycache__` 是什么
    Markdown 实现首行缩进
    LaTex 小技巧
    LaTeX算法排版 笔记
  • 原文地址:https://www.cnblogs.com/Enceladus/p/7115321.html
Copyright © 2011-2022 走看看