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
原文地址:https://www.cnblogs.com/Enceladus/p/7115321.html