#include using namespace std; #define REP(i,a,b) for(i=a;i int coordinateCompress(int n, T arr[], int res[], void *mem){ int i, k=0; pair*r=(pair*)mem; rep(i,n) r[i].first=arr[i], r[i].second=i; sort(r,r+n); if(res!=NULL){ rep(i,n){ if(i&&r[i].first!=r[i-1].first)k++; res[r[i].second]=k; } }else{ rep(i,n){ if(i&&r[i].first!=r[i-1].first)k++; arr[r[i].second]=k; } } return k+1; } char memarr[17000000]; void *mem = memarr; #define MD 1000000007 int get_inv(ll a, int md){ ll t=a, s=md, u=1, v=0, e; while(s){ e=t/s; t-=e*s; u-=e*v; swap(t,s); swap(u,v); } if(u<0) u+=md; return u; } struct mint{ static unsigned md, W, R, Rinv, mdninv, RR; unsigned val; mint(){} mint(int a){val = mulR(a);} mint(unsigned a){val = mulR(a);} mint(ll a){val = mulR(a);} mint(ull a){val = mulR(a);} unsigned setmod(unsigned m){ int i; unsigned t; W = 32; md = m; R = (1ULL << W) % md; RR = (ull)R*R % md; switch(m){ case 104857601: Rinv = 2560000; mdninv = 104857599; break; case 998244353: Rinv = 232013824; mdninv = 998244351; break; case 1000000007: Rinv = 518424770; mdninv = 2226617417U; break; case 1000000009: Rinv = 171601999; mdninv = 737024967; break; case 1004535809: Rinv = 234947584; mdninv = 1004535807; break; case 1007681537: Rinv = 236421376; mdninv = 1007681535; break; case 1012924417: Rinv = 238887936; mdninv = 1012924415; break; case 1045430273: Rinv = 254466304; mdninv = 1045430271; break; case 1051721729: Rinv = 257538304; mdninv = 1051721727; break; default: Rinv = get_inv(R, md); mdninv = 0; t = 0; rep(i,W){ if(t%2==0) t+=md, mdninv |= (1U<> W); if(t >= md) t -= md; return t; } unsigned reduce(ull T){ unsigned m = (unsigned)T * mdninv; unsigned t = (unsigned)((T + (ull)m*md) >> W); if(t >= md) t -= md; return t; } unsigned get(){ return reduce(val); } mint &operator+=(mint a){ val += a.val; if(val >= md) val -= md; return *this; } mint &operator-=(mint a){ if(val < a.val) val = val + md - a.val; else val -= a.val; return *this; } mint &operator*=(mint a){ val = reduce((ull)val*a.val); return *this; } mint &operator/=(mint a){ return *this *= a.inverse(); } mint operator+(mint a){ return mint(*this)+=a; } mint operator-(mint a){ return mint(*this)-=a; } mint operator*(mint a){ return mint(*this)*=a; } mint operator/(mint a){ return mint(*this)/=a; } mint operator+(int a){ return mint(*this)+=mint(a); } mint operator-(int a){ return mint(*this)-=mint(a); } mint operator*(int a){ return mint(*this)*=mint(a); } mint operator/(int a){ return mint(*this)/=mint(a); } mint operator+(ll a){ return mint(*this)+=mint(a); } mint operator-(ll a){ return mint(*this)-=mint(a); } mint operator*(ll a){ return mint(*this)*=mint(a); } mint operator/(ll a){ return mint(*this)/=mint(a); } mint operator-(void){ mint res; if(val) res.val=md-val; else res.val=0; return res; } operator bool(void){ return val!=0; } operator int(void){ return get(); } operator ll(void){ return get(); } mint inverse(){ int a = val, b = md, u = 1, v = 0, t; mint res; while(b){ t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); } if(u < 0) u += md; res.val = (ull)u*RR % md; return res; } mint pw(ull b){ mint a(*this), res; res.val = R; while(b){ if(b&1) res *= a; b >>= 1; a *= a; } return res; } bool operator==(int a){return get()==a;} bool operator!=(int a){return get()!=a;} }; unsigned mint::md, mint::W, mint::R, mint::Rinv, mint::mdninv, mint::RR; mint operator+(int a, mint b){return mint(a)+=b;} mint operator-(int a, mint b){return mint(a)-=b;} mint operator*(int a, mint b){return mint(a)*=b;} mint operator/(int a, mint b){return mint(a)/=b;} mint operator+(ll a, mint b){return mint(a)+=b;} mint operator-(ll a, mint b){return mint(a)-=b;} mint operator*(ll a, mint b){return mint(a)*=b;} mint operator/(ll a, mint b){return mint(a)/=b;} mint mval[10000], minv[10000]; void mint_init(int md=MD, mint val[]=mval, int vals=10000, mint inv[]=minv, int invs=10000){ int i; val[0].setmod(md); val[0].val = 0; REP(i,1,vals){ val[i].val = val[i-1].val + mint::R; if(val[i].val >= md) val[i].val -= md; } inv[1].val = 1; REP(i,2,invs){ inv[i].val = md - ((ll)(md/i)*inv[md%i].val%md); } REP(i,1,invs) inv[i].val = (ull)inv[i].val*mint::R%md; } template struct fenwick2d{ int sizeX, sizeY, memory; T *data; void malloc(int mem){ memory=mem; data=(T*)std::malloc(sizeof(T)*mem); } void *malloc(int mem, void *workMemory){ memory=mem; data=(T*)workMemory; return data+mem; } void init(int X, int Y){ sizeX=X; sizeY=Y; memset(data,0,sizeof(T)*X*Y); } void add(int x, int y, T val){ int k; while(x=0){ k=y; while(k>=0) res+=data[x*sizeY+k], k=(k&(k+1))-1; x=(x&(x+1))-1; } return res; } T range(int x1, int y1, int x2, int y2){ return get(x2,y2)-get(x1-1,y2)-get(x2,y1-1)+get(x1-1,y1-1); } }; template struct Treap{ struct node{ T val, ind; unsigned pri; node *lef, *rig; int size; T sum; T added; void init(T v, T i, unsigned p){ val = v; ind = i; pri = p; lef = rig = (node*)NULL; size = 1; sum = v; } node(T v, T i, unsigned p){ init(v,i,p); } node(T v, T i){ node(v, i, (unsigned)rand()); } }; node *root; Treap(){ root = (node*)NULL; } int size(node* u){ if(u==NULL) return 0; return u->size; } int size(void){ return size(root); } T get_sum(node *u){ if(u==NULL) return 0; return u->sum; } void add(node *u, T v){ if(u==NULL) return; u->added += v; u->sum += u->size * v; } void apply_added(node *u){ if(u==NULL || u->added==0) return; u->val += u->added; add(u->lef, u->added); add(u->rig, u->added); u->added = 0; } void apply(node *u){ apply_added(u); } node *update(node *u){ u->size = size(u->lef) + size(u->rig) + 1; apply(u); u->sum = get_sum(u->lef) + get_sum(u->rig) + u->val; return u; } node *merge(node *a, node *b){ if(a==NULL) return b; if(b==NULL) return a; apply(a); apply(b); if(a->pri > b->pri){ a->rig = merge(a->rig, b); return update(a); } else { b->lef = merge(a, b->lef); return update(b); } } pair split(node *u, int k){ pair t; if(u==NULL) return make_pair((node*)NULL,(node*)NULL); apply(u); if(k <= size(u->lef)){ t = split(u->lef, k); u->lef = t.second; return make_pair(t.first, update(u)); } else { int chk = k-size(u->lef)-1; t = split(u->rig, k-size(u->lef)-1); u->rig = t.first; return make_pair(update(u), t.second); } } void split(node *u, int k, node **s, node **t){ pair m = split(u,k); *s = m.first; *t = m.second; } node *insert(node *u, int k, T v, T i, unsigned p){ pair t = split(u, k); node *x = (node*)malloc(sizeof(node)); x->init(v,i,p); u = merge(t.first, x); u = merge(u, t.second); return update(u); } node *erase(node *u, int k){ pair s, t; s = split(u, k+1); t = split(s.first, k); u = merge(t.first, s.second); free(t.second); return update(u); } node *kth(node *u, int k){ int sz; apply(u); sz = size(u->lef); if(k==sz) return u; if(klef,k); return kth(u->rig,k-sz-1); } node *lower_bound_node(node *u, T k){ T s; if(u==NULL) return u; apply(u); s = get_sum(u->lef); if(k<=s){ node *res = lower_bound_node(u->lef, k); return res==NULL?u:res; } s += u->val; if(k<=s) return u; return lower_bound_node(u->rig,k-s); } int lower_bound(node *u, T k){ T s; int res = 0; if(u==NULL) return res; apply(u); s = get_sum(u->lef); if(k<=s) return lower_bound(u->lef, k); s += u->val; if(k<=s) return size(u->lef); return lower_bound(u->rig,k-s) + size(u->lef) + 1; } void insert(int k, T v, T i){ root = insert(root, k, v, i, (unsigned)rand()); } void erase(int k){ root = erase(root, k); } node *kth(int k){ return kth(root, k); } int lower_bound(int k){ return lower_bound(root, k); } node *lower_bound_node(int k){ return lower_bound_node(root, k); } void add(int a, int b, T v){ node *u[3]; split(root, a, &u[0], &root); split(root, b-a, &u[1], &u[2]); add(u[1], v); root = merge(u[0], u[1]); root = merge(root, u[2]); } T get_sum(int a, int b){ T res; node *u[3]; split(root, a, &u[0], &root); split(root, b-a, &u[1], &u[2]); res = get_sum(u[1]); root = merge(u[0], u[1]); root = merge(root, u[2]); return res; } int toArray(node *u, T res[]){ int k; if(u==NULL) return 0; apply(u); k = toArray(u->lef, res); res[k++] = u->val; k += toArray(u->rig, res+k); return k; } int toArray(T res[]){ return toArray(root, res); } int toArray(int a, int b, T res[]){ node *u[3]; split(root, a, &u[0], &root); split(root, b-a, &u[1], &u[2]); toArray(u[1], res); root = merge(u[0], u[1]); root = merge(root, u[2]); return b-a; } int toArrayInd(node *u, T res[]){ int k; if(u==NULL) return 0; apply(u); k = toArrayInd(u->lef, res); res[k++] = u->ind; k += toArrayInd(u->rig, res+k); return k; } int toArrayInd(T res[]){ return toArrayInd(root, res); } int toArrayInd(int a, int b, T res[]){ node *u[3]; split(root, a, &u[0], &root); split(root, b-a, &u[1], &u[2]); toArrayInd(u[1], res); root = merge(u[0], u[1]); root = merge(root, u[2]); return b-a; } }; #define B 50 int N, Q; int A[200000]; int MODE[100000], ind[100000]; int X[100000], Y[100000]; int m; mint val[200000]; int Aind[200000]; int arr[200001], iarr[200001]; set place[200000]; set::iterator ht, it, jt; fenwick2d t[4]; void setadd(int p, int v){ int i; mint tmp[4]; tmp[0] = mval[1]; REP(i,1,4) tmp[i]=tmp[i-1]*val[v]; arr[p] = v; place[v].insert(p); ht = it = jt = place[v].find(p); jt++; if(it != place[v].begin()){ ht--; rep(i,4) t[i].add((*ht)/B, (*it)/B, -tmp[i]); if(jt != place[v].end()) rep(i,4) t[i].add((*ht)/B, (*jt)/B, tmp[i]); } rep(i,4) t[i].add((*it)/B, (*it)/B, tmp[i]); if(jt != place[v].end()){ rep(i,4) t[i].add((*it)/B, (*jt)/B, -tmp[i]); } } void setdel(int p){ int i, v = arr[p]; mint tmp[4]; tmp[0] = mval[1]; REP(i,1,4) tmp[i]=tmp[i-1]*val[v]; ht = it = jt = place[v].find(p); jt++; if(it != place[v].begin()){ ht--; rep(i,4) t[i].add((*ht)/B, (*it)/B, tmp[i]); if(jt != place[v].end()) rep(i,4) t[i].add((*ht)/B, (*jt)/B, -tmp[i]); } rep(i,4) t[i].add((*it)/B, (*it)/B, -tmp[i]); if(jt != place[v].end()){ rep(i,4) t[i].add((*it)/B, (*jt)/B, tmp[i]); } place[v].erase(it); arr[p] = -1; } mint get1(int lef, int rig){ int i, j, k, a, x, st, ed; mint p1, p2, p3, e1, e2, e3; p1 = p2 = p3 = mval[0]; st = (lef+B-1) / B; ed = (rig+1) / B - 1; if(st <= ed){ p1 += t[1].range(st, st, ed, ed); p2 += t[2].range(st, st, ed, ed); p3 += t[3].range(st, st, ed, ed); REP(a, lef, st*B) if(arr[a]>=0){ x = arr[a]; it = place[x].find(a); it++; if(it==place[x].end() || (*it) >= (ed+1)*B){ p1 += val[x]; p2 += val[x]*val[x]; p3 += val[x]*val[x]*val[x]; } } REP(a, (ed+1)*B, rig+1) if(arr[a]>=0){ x = arr[a]; it = place[x].find(a); if(it==place[x].begin() || *(--it) < lef){ p1 += val[x]; p2 += val[x]*val[x]; p3 += val[x]*val[x]*val[x]; } } } else { REP(a, lef, rig+1) if(arr[a]>=0){ x = arr[a]; it = place[x].find(a); it++; if(it==place[x].end() || (*it) > rig){ p1 += val[x]; p2 += val[x]*val[x]; p3 += val[x]*val[x]*val[x]; } } } e1 = p1; e2 = (e1*p1 - p2) * minv[2]; e3 = (e2*p1 - e1*p2 + p3) * minv[3]; return e3; } mint get5(int lef, int rig){ int i, j, k, a, x, st, ed; mint res = mval[0]; st = (lef+B-1) / B; ed = (rig+1) / B - 1; if(st <= ed){ res += t[0].range(st, st, ed, ed); REP(a, lef, st*B) if(arr[a]>=0){ x = arr[a]; it = place[x].find(a); it++; if(it==place[x].end() || (*it) >= (ed+1)*B){ res += mval[1]; } } REP(a, (ed+1)*B, rig+1) if(arr[a]>=0){ x = arr[a]; it = place[x].find(a); if(it==place[x].begin() || *(--it) < lef){ res += mval[1]; } } } else { REP(a, lef, rig+1) if(arr[a]>=0){ x = arr[a]; it = place[x].find(a); it++; if(it==place[x].end() || (*it) > rig){ res += mval[1]; } } } return res; } int main(){ int i, j, k, a, st, ed; int x, bef, aft, sz; Treap treap; Treap::node *node; mint res; mint_init(); scanf("%d%d",&N,&Q); rep(i,N) scanf("%d",A+i); rep(i,Q){ scanf("%d ",MODE+i); if(MODE[i]!=3){ scanf("%d%d",X+i,Y+i); } else { scanf("%d",X+i); } } k = 0; rep(i,N) arr[k++] = A[i]; rep(i,Q) if(MODE[i]==2||MODE[i]==4) arr[k++] = Y[i]; m = coordinateCompress(k, arr, NULL, mem); k = 0; rep(i,N){ val[arr[k]] = mint(A[i]); A[i] = arr[k]; k++; } rep(i,Q) if(MODE[i]==2 || MODE[i]==4){ val[arr[k]] = mint(Y[i]); Y[i] = arr[k]; k++; } rep(i,N) treap.insert(i, 1, i); rep(i,Q){ if(MODE[i]==1 || MODE[i]==5){ node = treap.lower_bound_node(X[i]); X[i] = node->ind; node = treap.lower_bound_node(Y[i]); Y[i] = node->ind; } if(MODE[i]==2){ node = treap.lower_bound_node(X[i]); X[i] = node->ind; } if(MODE[i]==3){ node = treap.lower_bound_node(X[i]); j = node->ind; k = treap.lower_bound(X[i]); treap.add(k, k+1, -1); X[i] = j; } if(MODE[i]==4){ k = treap.lower_bound(X[i]+1); X[i] = N+i; treap.insert(k, 1, N+i); } } sz = treap.toArrayInd(arr); rep(i,sz) iarr[arr[i]] = i; rep(i,4) t[i].malloc((sz/B)*(sz/B)); rep(i,4) t[i].init(sz/B, sz/B); rep(i,N) Aind[i] = iarr[i]; rep(i,Q){ if(MODE[i]==1 || MODE[i]==5){ X[i] = iarr[X[i]]; Y[i] = iarr[Y[i]]; } if(MODE[i]==2 || MODE[i]==3 || MODE[i]==4){ X[i] = iarr[X[i]]; } } k = treap.get_sum(treap.root); rep(i,sz) arr[i] = -1; rep(i,N) setadd(Aind[i], A[i]); rep(i,Q){ if(MODE[i]==1){ res = get1(X[i], Y[i]); printf("%d\n",(int)res); } else if(MODE[i]==2){ setdel(X[i]); setadd(X[i], Y[i]); } else if(MODE[i]==3){ setdel(X[i]); } else if(MODE[i]==4){ setadd(X[i], Y[i]); } else if(MODE[i]==5){ res = get5(X[i], Y[i]); printf("%d\n",(int)res); } } return 0; }