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;

}

  

 

你可能感兴趣的:(ICE)