牛客小白月赛12 F华华开始学信息学 (分块+树状数组)
鏈接:https://ac.nowcoder.com/acm/contest/392/F
來源:牛客網(wǎng)
時間限制:C/C++ 2秒,其他語言4秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
題目描述
因為上次在月月面前丟人了,所以華華決定開始學(xué)信息學(xué)。十分鐘后,他就開始學(xué)樹狀數(shù)組了。這是一道樹狀數(shù)組的入門題:
給定一個長度為N的序列A,所有元素初值為0。接下來有M次操作或詢問:
操作:輸入格式:1 D K,將A_DA
D
?
加上K。
詢問:輸入格式:2 L R,詢問區(qū)間和,即\sum_{i=L}^{R}A_i∑
i=L
R
?
A
i
?
。
華華很快就學(xué)會了樹狀數(shù)組并通過了這道題。月月也很喜歡樹狀數(shù)組,于是給華華出了一道進(jìn)階題:
給定一個長度為N的序列A,所有元素初值為0。接下來有M次操作或詢問:
操作:輸入格式:1 D K,對于所有滿足1\le i\le N1≤i≤N且i\equiv0(\mod D)i≡0(modD)的i,將A_iA
i
?
加上K。
詢問:輸入格式:2 L R,詢問區(qū)間和,即\sum_{i=L}^{R}A_i∑
i=L
R
?
A
i
?
。
華華是個newbie,怎么可能會這樣的題?不過你應(yīng)該會吧。
輸入描述:
第一行兩個正整數(shù)N、M表示序列的長度和操作詢問的總次數(shù)。
接下來M行每行三個正整數(shù),表示一個操作或詢問。
輸出描述:
對于每個詢問,輸出一個非負(fù)整數(shù)表示答案。
示例1
輸入
復(fù)制
10 6
1 1 1
2 4 6
1 3 2
2 5 7
1 6 10
2 1 10
輸出
復(fù)制
3
5
26
備注:
1\le N,M\le10^51≤N,M≤10
5
,1\le D\le N1≤D≤N,1\le L\le R\le N1≤L≤R≤N,1\le K \le 10^81≤K≤10
8
思路:
這里我用 laze[i] 代表 i的倍數(shù)被加多少值
詢問的時候暴力掃1~sqrtn 的laze,同時用數(shù)論分塊可以知道 區(qū)間中i的倍數(shù)有多少個,計算貢獻(xiàn)即可。
推薦博客:https://www.cnblogs.com/zjl192628928/p/10544105.html
細(xì)節(jié)見代碼:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl using namespace std; typedef long long ll; ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} ll lcm(ll a, ll b) {return a / gcd(a, b) * b;} ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;} inline void getInt(int* p); const int maxn = 100010; const int inf = 0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ ll tree[maxn]; int n; int lowbit(int x) {return x & (-1 * x); } void add(int x, ll val) {while (x <= n){tree[x] += val;x += lowbit(x);} } ll ask(int x) {ll res = 0ll;while (x){res += tree[x];x -= lowbit(x);}return res; } ll laze[maxn]; // ll n; int main() {//freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);//freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);int m;scanf("%d", &n);scanf("%d", &m);int blocks=(int)(sqrt(n)+0.5);while(m--){int op,l,r;scanf("%d %d %d",&op,&l,&r);if(op==1){if(l>=blocks){for(int i=l;i<=n;i+=l){add(i,1ll*r);}}else{laze[l]+=r;}}else{ll ans=ask(r)-ask(l-1);repd(i,1,blocks){ans+=laze[i]*(r/i-(l-1)/i);}printf("%lld\n",ans );}}return 0; }inline void getInt(int* p) {char ch;do {ch = getchar();} while (ch == ' ' || ch == '\n');if (ch == '-') {*p = -(getchar() - '0');while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 - ch + '0';}}else {*p = ch - '0';while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 + ch - '0';}} }轉(zhuǎn)載于:https://www.cnblogs.com/qieqiemin/p/11421197.html
總結(jié)
以上是生活随笔為你收集整理的牛客小白月赛12 F华华开始学信息学 (分块+树状数组)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习C语言的工具
- 下一篇: 牛客小白月赛12 D月月给华华出题 (