题意:给定一个正整数序列,操作是1.区间赋值,2.区间大于x的数与x取gcd,最后输出操作后的序列
用平衡树维护相同数组成的连续段,每次操作至多增加两个连续段,操作2记录一下区间最小值然后暴力修改,每个数在被修改次数不会超过质因数个数,于是均摊单次修改复杂度在log^2(n)左右
#include<bits/stdc++.h> char buf[12000000],*ptr=buf-1; int _(){ int x=0,c=*++ptr; while(c<48)c=*++ptr; while(c>47)x=x*10+c-48,c=*++ptr; return x; } int gcd(int a,int b){ for(int c;b;c=a,a=b,b=c%b); return a; } void mins(int&a,int b){if(a<b)a=b;} int T; struct node{ int l,r,x,mx,rnd; node*lc,*rc; void pr(){ if(!this)return; lc->pr(); for(int i=l;i<=r;++i)printf("%d ",x); rc->pr(); } void up(){ mx=x; if(lc)mins(mx,lc->mx); if(rc)mins(mx,rc->mx); } void gcds(int v){ if(!this||mx<=v)return; if(x>v)x=gcd(x,v); lc->gcds(v); rc->gcds(v); up(); } }ns[100055],*ss[100055],*rt; struct drt{node*lc,*rc;}; int sp=0; node*_new(int l,int r,int x){ node*w=ss[--sp]; w->l=l;w->r=r;w->mx=w->x=x; return w; } void del(node*&w){ if(!w)return; del(w->lc); del(w->rc); ss[sp++]=w; w=0; } node*merge(node*a,node*b){ if(!a)return b; if(!b)return a; if(a->rnd>b->rnd){ a->rc=merge(a->rc,b); a->up(); return a; } b->lc=merge(a,b->lc); b->up(); return b; } drt split(node*w,int x){ if(!w)return (drt){0,0}; drt m; if(w->l>=x){ m=split(w->lc,x); w->lc=m.rc; m.rc=w; w->up(); return m; } if(w->r<x){ m=split(w->rc,x); w->rc=m.lc; m.lc=w; w->up(); return m; } node*u=m.lc=_new(w->l,x-1,w->x); u->lc=w->lc; u->up(); m.rc=w; w->lc=0;w->l=x; w->up(); return m; } int main(){ fread(buf,1,sizeof(buf),stdin); srand(29139); for(int i=1;i<=100050;++i)(ss[sp++]=ns+i)->rnd=rand(); for(T=_();T;--T){ int n=_(); rt=0; for(int i=1;i<=n;++i){ node*w=_new(i,i,_()); rt=merge(rt,w); } for(int q=_(),o,l,r,x;q;--q){ o=_();l=_();r=_();x=_(); if(o==1){ drt a=split(rt,l); drt b=split(a.rc,r+1); del(b.lc); node*w=_new(l,r,x); rt=merge(a.lc,merge(w,b.rc)); }else{ drt a=split(rt,l); drt b=split(a.rc,r+1); b.lc->gcds(x); rt=merge(a.lc,merge(b.lc,b.rc)); } } rt->pr(); putchar(10); del(rt); } return 0; }