1 10 16807 282475249 1622650073 984943658 1144108930 470211272 101027544 1457850878 1458777923 2007237709 10 1 3 6 74243042 2 4 8 16531729 1 3 4 1474833169 2 1 8 1131570933 2 7 9 1505795335 2 3 7 101929267 1 4 10 1624379149 2 2 8 2110010672 2 6 7 156091745 1 2 5 937186357
16807 937186357 937186357 937186357 937186357 1 1 1624379149 1624379149 1624379149
涉及到更新区间(成段更新)时,有一个技巧lazy_tag,在线段树子树加上tag,表示这个子树包含某些性质或者要进行某些操作,不用立即访问到这个子树的叶子,只有当下一次仍需访问这个子树下的节点时才继续进行。lazy_tag技巧可以用于下面几个方面:
1、区间加一个数。(这里的加可以变为任何满足区间加法的操作,比如区间异或,区间求GCD)。
2、区间变为一个数。
3、区间最值。
4、给出01序列,区间取反。
5、区间最长连续1的序列。
6、区间最长子段和。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; struct nod{ int l,r; int s; }a[400100]; void build(int root,int l,int r){ a[root].l=l; a[root].r=r; a[root].s=-1; if(l==r){ scanf("%d",&a[root].s); return ; } if(l<r){ int mid=(l+r)>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); if(a[root<<1].s==a[root<<1|1].s) a[root].s=a[root<<1].s; } } void update1(int root,int l,int r,int val){ if(a[root].l==l&&a[root].r==r){ a[root].s=val; return ; } if(a[root].s>=0){//lazy ЛјПл a[root<<1].s=a[root].s; a[root<<1|1].s=a[root].s; a[root].s=-1; } int mid=(a[root].l+a[root].r)>>1; if(r<=mid) update1(root<<1,l,r,val); else if(l>mid) update1(root<<1|1,l,r,val); else{ update1(root<<1,l,mid,val); update1(root<<1|1,mid+1,r,val); } } int gcd(int a,int b){ if(b) return gcd(b,a%b); return a; } void update2(int root,int l,int r,int val){ if(a[root].l==l&&a[root].r==r&&a[root].s>=0){ if(a[root].s>val) a[root].s=gcd(a[root].s,val); return ; } if(a[root].s>=0){ a[root<<1].s=a[root].s; a[root<<1|1].s=a[root].s; a[root].s=-1; } int mid=(a[root].l+a[root].r)>>1; if(r<=mid) update2(root<<1,l,r,val); else if(l>mid) update2(root<<1|1,l,r,val); else{ update2(root<<1,l,mid,val); update2(root<<1|1,mid+1,r,val); } } void output(int root){ if(a[root].s>=0){ for(int i=a[root].l;i<=a[root].r;i++) printf("%d ",a[root].s); return ; } output(root<<1); output(root<<1|1); } int main() { int q,t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); // cout<<"1****"<<endl; build(1,1,n); // cout<<"2****"<<endl; scanf("%d",&q); int o,l,r; int x; while(q--){ scanf("%d%d%d%d",&o,&l,&r,&x); // cout<<"3****"<<endl; if(o==1){ update1(1,l,r,x); // cout<<"4***"<<endl; } else if(o==2) update2(1,l,r,x); } output(1); printf("\n"); } return 0; }