线段树--CF438D The Child and Sequence

*洛谷传送

学校集训的第二天不知不觉写了道紫题(〃'▽'〃)(〃'▽'〃)(〃'▽'〃)

对于操作1和3,赤裸裸的线段树板子。单点修改和区间求和复杂度都没有什么问题,关键就在取模。对一个数取模,假如一段区间最大值都比这个模数小,那无论怎么改,其值都不会变,有了这个性质,我们可以去掉许多不必要的操作,由于一次取模至少会砍一半,所以在log的时间内就可以完成对一个数的所有取模操作,这样就可做了,因此我们额外维护一个区间最大值即可。

另一道题花神游历各国可以试着练练手。

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 #define ll long long
 7 #define re register
 8 #define il inline 
 9 const int maxn=1e6+10;
10 ll n,m,a[maxn],tree[2*maxn],lazy[2*maxn],x,y,k,mark,tree1[2*maxn];
11 il int ls(ll x){return x<<1;}
12 il int rs(ll x){return x<<1|1;}
13 il void pushup(ll x){
14     tree[x]=tree[ls(x)]+tree[rs(x)];
15     tree1[x]=max(tree1[ls(x)],tree1[rs(x)]);
16 }
17 il void build(ll x,ll l,ll r){
18     if(l==r){tree[x]=a[l];tree1[x]=a[l];return;}
19     ll mid=(l+r)>>1;
20     build(ls(x),l,mid);
21     build(rs(x),mid+1,r);
22     pushup(x); 
23 }
24 il void update(ll x,ll l,ll r,ll k,ll w){
25     if (l==r&&r==k){tree[x]=w;tree1[x]=w;return;}
26     ll mid=(l+r)>>1;
27     if (k<=mid) update(ls(x),l,mid,k,w);
28     if (k>mid) update(rs(x),mid+1,r,k,w);
29     pushup(x);
30 }
31 
32 il void update1(ll x,ll l,ll r,ll nl,ll nr,ll k){
33     if (tree1[x]<k) return;
34     if (nl<=l&&r<=nr&&l==r){tree[x]=(tree[x]%k);tree1[x]=(tree1[x]%k);return;}
35     ll mid=(l+r)>>1;
36     if (nl<=mid) update1(ls(x),l,mid,nl,nr,k);
37     if (nr>mid) update1(rs(x),mid+1,r,nl,nr,k);
38     pushup(x);
39 }
40 il ll query(ll x,ll l,ll r,ll nl,ll nr){
41     ll ans=0;
42     if (nl<=l&&r<=nr)return tree[x];
43     ll mid=(l+r)>>1;
44     if (nl<=mid) ans+=query(ls(x),l,mid,nl,nr);
45     if (nr>mid) ans+=query(rs(x),mid+1,r,nl,nr);
46     return ans;
47 }
48 il ll query1(ll x,ll l,ll r,ll nl,ll nr){
49     ll ans=0;
50     if (nl<=l&&r<=nr)return tree1[x];
51     ll mid=(l+r)>>1;
52     if (nl<=mid) ans=max(query1(ls(x),l,mid,nl,nr),ans);
53     if (nr>mid) ans=max(query1(rs(x),mid+1,r,nl,nr),ans);
54     return ans;
55 }
56 int main(){
57 //    freopen("mod.in","r",stdin);
58 //    freopen("mod.out","w",stdout);
59     scanf ("%d%d",&n,&m);
60     for (re ll i = 1;i <= n;i++) scanf ("%lld",&a[i]);
61     build (1,1,n);
62     for(re ll i = 1;i <= m;i++){
63         scanf ("%lld",&mark);
64         if (mark==1){
65             scanf ("%lld%lld",&x,&y);
66             ll tmp=query(1,1,n,x,y);
67             printf ("%lld
",tmp);
68         }
69         if (mark==2){
70             scanf ("%lld%lld%lld",&x,&y,&k);
71             ll tmp=query1(1,1,n,x,y);
72             if (tmp<k) continue;
73             update1(1,1,n,x,y,k);
74         }
75         if (mark==3){
76             scanf ("%lld%lld",&k,&y);
77             update(1,1,n,k,y);
78         }
79     }
80     return 0;
81 }
原文地址:https://www.cnblogs.com/very-beginning/p/13566567.html