BZOJ3867 : Nice boat
每个点最多被修改$O(\log n)$次,线段树记录区间最值暴力更新。
#include<cstdio> #define N 262145 int T,n,m,i,op,c,d,p,s[N],v[N],tag[N]; inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';} int gcd(int a,int b){return b?gcd(b,a%b):a;} inline void up(int x){v[x]=v[x<<1]>v[x<<1|1]?v[x<<1]:v[x<<1|1];tag[x]=tag[x<<1]==tag[x<<1|1]?tag[x<<1]:-1;} inline void pb(int x){if(~tag[x])tag[x<<1]=tag[x<<1|1]=v[x<<1]=v[x<<1|1]=tag[x];} void build(int x,int a,int b){ if(a==b){tag[x]=v[x]=s[a];return;} int mid=(a+b)>>1; build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x); } void change1(int x,int a,int b){ if(c<=a&&b<=d){tag[x]=v[x]=p;return;} pb(x); int mid=(a+b)>>1; if(c<=mid)change1(x<<1,a,mid); if(d>mid)change1(x<<1|1,mid+1,b); up(x); } void change2(int x,int a,int b){ if(v[x]<=p)return; int mid=(a+b)>>1; if(c<=a&&b<=d){ if(~tag[x])v[x]=tag[x]=gcd(tag[x],p); else pb(x),change2(x<<1,a,mid),change2(x<<1|1,mid+1,b),up(x); return; } pb(x); if(c<=mid)change2(x<<1,a,mid); if(d>mid)change2(x<<1|1,mid+1,b); up(x); } void dfs(int x,int a,int b){ if(~tag[x]){for(;a<=b;a++)printf("%d ",tag[x]);return;} int mid=(a+b)>>1; dfs(x<<1,a,mid),dfs(x<<1|1,mid+1,b); } int main(){ read(T); while(T--){ read(n); for(i=1;i<=n;i++)read(s[i]); build(1,1,n); read(m); while(m--)read(op),read(c),read(d),read(p),op==1?change1(1,1,n):change2(1,1,n); dfs(1,1,n); puts(""); } return 0; }