日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces 390E Inna and Large Sweet Matrix(树状数组改段求段)

發(fā)布時(shí)間:2025/7/14 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces 390E Inna and Large Sweet Matrix(树状数组改段求段) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
CodeForces 390E Inna and Large Sweet Matrix(樹狀數(shù)組改段求段)

樹狀數(shù)組僅僅能實(shí)現(xiàn)線段樹區(qū)間改動(dòng)和區(qū)間查詢的功能,能夠取代不須要lazy tag的線段樹。且代碼量和常數(shù)較小

首先定義一個(gè)數(shù)組 int c[N]; 并清空 memset(c, 0, sizeof c);

1、單點(diǎn)改動(dòng) : c[x] += y; 相應(yīng)的函數(shù)是 change(x, y);

2、求前綴和 :??相應(yīng)的函數(shù)是 int sum(x)

兩種操作的復(fù)雜度都是O(logn)

模板例如以下:

int c[N], maxn; inline int Lowbit(int x){return x&(-x);} void change(int i, int x)//i點(diǎn)增量為x { while(i <= maxn) { c[i] += x; i += Lowbit(i); } } int sum(int x){//區(qū)間求和 [1,x] int ans = 0; for(int i = x; i >= 1; i -= Lowbit(i)) ans += c[i]; return ans; }

怎樣運(yùn)用樹狀數(shù)組進(jìn)行區(qū)間操作

先定義兩個(gè)樹狀數(shù)組 X, Y

如今我們須要對(duì)一個(gè)數(shù)組 int a[N]; 進(jìn)行區(qū)間操作:[L, R] += val 即 for i:L to R a[i] += val;?

再定義一個(gè) int size = R-L+1 , 即區(qū)間長度

相應(yīng)的改動(dòng)是?

1、X[L] += val; ? X[R+1] -= val;

2、Y[L] += -1 * val * (L-1); ? Y[R+1] += val * R;

相應(yīng)的查詢是

當(dāng)我們求和??時(shí)在樹狀數(shù)組中操作是 ans = X.sum(k) * k + Y.sum(k)

分類討論一下k分別在 [1,L-1] , [L, R] , [R+1, +]

1、k[1,L-1] ?

顯然 X.sum(k) == 0 且 Y.sum(k) == 0 -> ans = X.sum(k)*k + Y.sum(k) = 0*i+0 = 0 結(jié)果與實(shí)際相符。

2、k[L, R]?

X.sum(k) * k = X[L] * k = val * k, ? Y.sum(k) = Y[L] = ?-1 * val * (L-1)?

ans = val * k - val * (L-1) = val * ( k - (L-1) );?

3、k[R+1,?]

X.sum(k) * k = ( x[L] + x[R] ) * k = 0 * k = 0;

Y.sum(k) = Y[L] + Y[R] = -val * (L-1) + val * R = val * (R-L+1) = val * size

X.sum(k) * k + Y.sum(k) = val * size

證明完成。

下面模版中兩個(gè)樹狀數(shù)組c[0], c[1] 相應(yīng)上述的X, Y

區(qū)間改動(dòng):add(L, R, val)

求 int a[N]的前綴和 get_pre(R)

區(qū)間查詢:get(L,R)

const int N = 4e5 + 100; template<class T> struct Tree{T c[2][N];int maxn;void init(int x){maxn = x+10; memset(c, 0, sizeof c);}inline int lowbit(int x){ return x&-x; }T sum(T *b, int x){T ans = 0;if (x == 0)ans = b[0];while (x)ans += b[x], x -= lowbit(x);return ans;}void change(T *b, int x, T value){if (x == 0)b[x] += value, x++;while (x <= maxn)b[x] += value, x += lowbit(x);}T get_pre(int r){return sum(c[0], r) * r + sum(c[1], r);}void add(int l, int r, T value){//區(qū)間加權(quán)change(c[0], l, value);change(c[0], r + 1, -value);change(c[1], l, value * (-l + 1));change(c[1], r + 1, value * r);}T get(int l, int r){//區(qū)間求和return get_pre(r) - get_pre(l - 1);} }; Tree<ll> tree;
好了,回歸正題,我們來講一下這道題的題意:

題意:給定n*m的二維平面 w個(gè)操作

int mp[n][m] = { 0 };

1、0 (x1,y1) (x2,y2) value

for i : x1 to x2

for j : y1 to y2?

mp[i][j] += value;

2、1 (x1, y1) (x2 y2)

ans1 = 縱坐標(biāo)在 y1,y2間的總數(shù)

ans2 = 橫坐標(biāo)不在x1,x2間的總數(shù)

puts(ans1-ans2);

代碼例如以下:

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std;typedef long long ll; const int N = 4e6+10; int n, m, w; template<class T> struct Tree { ll c[2][N]; int maxn; void init(int x){ maxn = x+10; memset(c, 0, sizeof c); } inline int lowbit(int x){ return x&-x; } ll sum(ll *b, int x){ ll ans = 0; if (x == 0)ans = b[0]; while (x)ans += b[x], x -= lowbit(x); return ans; } void change(ll *b, int x, ll value){ if (x == 0)b[x] += value, x++; while (x <= maxn)b[x] += value, x += lowbit(x); } ll get_pre(int r){ return sum(c[0], r) * r + sum(c[1], r); } void add(int l, int r, ll value){ change(c[0], l, value); change(c[0], r + 1, -value); change(c[1], l, value * (-l + 1)); change(c[1], r + 1, value * r); } ll get(int l, int r){ return get_pre(r) - get_pre(l - 1); } };Tree<ll> x, y; int main() {scanf("%d%d%d", &n, &m, &w);x.init(n); y.init(m); int tmp;ll all = 0;while(w--){scanf("%d", &tmp);int x1, x2, y1, y2, v;if(tmp == 0){scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &v);all += v * (x2-x1+1) * (y2-y1+1);x.add(x1, x2, v * (y2 - y1 + 1));y.add(y1, y2, v * (x2 - x1 + 1));}if(tmp == 1){scanf("%d%d%d%d", &x1, &y1, &x2, &y2);printf("%I64d\n", y.get(1, y2) - y.get(1, y1-1) - (all - x.get(1, x2) + x.get(1, x1 - 1))); }}return 0; }






posted on 2017-04-28 11:55 mthoutai 閱讀(...) 評(píng)論(...) 編輯 收藏

轉(zhuǎn)載于:https://www.cnblogs.com/mthoutai/p/6780958.html

總結(jié)

以上是生活随笔為你收集整理的CodeForces 390E Inna and Large Sweet Matrix(树状数组改段求段)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。