1. 程式人生 > 實用技巧 >線段樹--CF438D The Child and Sequence

線段樹--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\n",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 }