線段樹高階 區間取模

2021-09-25 13:45:42 字數 2249 閱讀 2150

題目要求的操作:

1 區間求和

2 區間取模

3 單點修改

這道題目不要用到 lazy陣列,因為條件是單點修改,直接修改的葉子節點,其次區間取模操作直接可以暴力。

a mod b分為兩種情況 1(a < b)2(a >= b)

對於第一種情況 我們不用操作,對自己大的數取模就是自己。

第二種情況 取模操作後a的值至少會減少一半 即:a <= a/2。

設 b + n = a。

a % b = (b + n)% b = ((b%b)+(n%b)) % b

此時有兩種情況 1。n >b   2。 n < = b

第一種情況:n >= b 我們可以重複第一步驟 將n替換成(n1 + b) = n,直到 最後的 ni < b為止。

第二種情況:此時的 a%b = n成立。又有 (n+b = a,n < b)這兩個條件 。得 n + n < a , n所以 a%b <= a/2;

這最壞就是二分情況,時間複雜度為 o(log2 n) 在int範圍內我們可以接受。

我們在這裡要儲存兩個值,乙個是區間和,乙個是區間的最大值(來判斷要不要進行取模操作)。剩下的就是線段樹的模板了

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define  ll long long

#define ull unsigned long long

#define mod 1000000007

#define inf 0x7ffffff

#define mem(a,b) memset(a,b,sizeof(a))

#define modd(a,b) (((a%b)+b)%b)

#define maxn 100010

using namespace std;

ll sum[maxn << 2];

ll mx[maxn << 2];

ll a[maxn];

int lazy[maxn << 2];

int r[maxn];

void pushup(int rt)

/*void pushdown(int ln,int rn,int rt)

}*/void buildtree(int l,int r,int rt)

int mid = (l + r) >> 1;

buildtree(l,mid,rt << 1);

buildtree(mid + 1,r,rt << 1 | 1);

pushup(rt);

}void update(int l,int l,int r,int rt,ll v)

int mid = (l + r) >> 1;

//pushdown(mid - l + 1,r - mid,rt);

if(l <= mid) update(l,l,mid,rt << 1,v);

else update(l,mid + 1,r,rt << 1 | 1,v);

pushup(rt);

}void update_mod(int l,int r,int l,int r,int rt,ll v)

int mid = (l + r) >> 1;

if(l <= mid) update_mod(l,r,l,mid,rt << 1,v);

if(r > mid) update_mod(l,r,mid + 1,r,rt << 1 | 1,v);

pushup(rt);

}ll query(int l,int r,int l,int r,int rt)

int mid = (l + r) >> 1;

// pushdown(mid - l + 1, r - mid,rt);

ll ans = 0;

if(l <= mid) ans += query(l,r,l,mid,rt << 1);

if(r > mid) ans += query(l,r,mid + 1,r,rt << 1 | 1);

return ans;

}int main()

if(opt[0] == '1')

if(opt[0] == '3')

}return 0;

}

zoj3886(線段樹,區間取模)

因為乙個數最多只需要log n 次就會變成1,而模數大於他本身,他又不會變化,最次每次o n 修改區間,最多也不會多過log n 次,所以複雜度是正確的。暴力修改就好 niconico數 所有比x小的數且與x互質的數,從小到大排列是乙個等差數列,則x為niconico數。容易證明 niconico數...

ZKW線段樹區間加區間取最值

本來以為是和zkw單點修改之類的簡單技巧,但是今天卡常的時候學習了一下發現有點離譜。rx tr x trx 表示max f ax max x max max maxfax maxx 也就是線段樹上乙個節點和他父親區間最大值的差分,我們現在可以知道乙個線段樹上乙個整區間的最大值就是他到根的和。那麼我們...

線段樹(區間樹)

目錄 為什麼要使用線段樹 什麼是線段樹 線段樹融合介面 線段樹實現 線段樹例題 融合介面 author administrator param public inte ce merger package com.suanfa.segmenttree 線段樹 區間樹 author administra...