CDOJ 1292 卿學姐種花 暴力 分塊 線段樹

2022-03-31 15:52:32 字數 4190 閱讀 1476

眾所周知,在喵哈哈村,有乙個溫柔善良的卿學姐。

卿學姐喜歡和她一樣美麗的花。所以卿學姐家的後院有很多的花壇。

卿學姐有\(n\)個花壇,一開始第\(i\)個花壇裡有\(a[i]\)朵花。每過一段時間,卿學姐都會在花壇裡種上新的花。

作為乙個聰明的學姐,卿學姐的種花方式也是與眾不同 , 每一次,卿學姐會在第\(x\)個花壇種上\(y\)朵花,然後在第\(x+1\)個花壇上種上\(y-1\)朵花,再在第\(x+2\)個花壇上種上\(y-2\)朵花......以此類推,直到種到最後乙個花壇,或者不需要種花為止。

喵哈哈的村民們都喜歡去卿學姐的後院賞花,沈寶寶也不例外。然而沈寶寶可不是省油的燈,怎麼可能會老老實實地賞花呢。每次沈寶寶來時,都會隨機詢問卿學姐在第\(i\)個花壇有多少朵花。

花壇的花實在太多了,卿學姐實在是數不過來。於是現在她向你求助,希望你能幫她數出花壇裡多少朵花。

第一行輸入兩個整數,花壇個數\(n\)和操作次數\(q\)。

第二行\(n\)個整數\(a[1],a[2],a[3].....a[n]\)。 ( $1 \leq a[i] \leq 2^ $ )

接下來\(q\)行,每行乙個操作。

1 x y表示卿學姐會在\(x\)號花壇種\(y\)朵花,並按相應的規律在後面的花壇上種花。

2 x表示沈寶寶問卿學姐第\(x\)個花壇有多少朵花。

資料保證:

對於每個詢問操作,按順序輸出答案對\(772002 + 233\)取模的值。

6 31 2 3 2 1 2

1 2 3

2 32 652

最簡單的方法,o(n)去更新,然後o(1)去查詢就好了,但是顯然這樣子會tle的

然後我們注意,我們發現這道保證查詢操作的sigmax<=1e8

所以我們把這個變成o(1)更新,o(n)查詢就好了,這個東西打個延時標記就好了。

比如1 x y

我只需要使得lazy[x]+=y,表示x這個位置需要往下更新的大小增加y

ed[x+y]++,表示某乙個更新會在x+y這個位置停止。

num[x]++,表示x這個位置多了乙個更新。

然後我們查詢2 x的時候

我們只需要從1這個位置,一直for到x這個位置就好了,然後處理我們剛才打上去的延遲標記。

add表示現在累計了多少的值,num表示現在我有多少個更新。

add+=lazy[i],

num+=num[i],num-=ed[i]。

a[i] = (a[i]+add)%mod;

add-=num。顯然走一步,就會減少num

然後就完了~

然後有人會深入去思考,假設沒有那個 sigma x<=1e8怎麼辦?

其實查詢和更新均攤一下就好了:

有兩種,

1.分塊,這個方法可以把查詢和更新操作都均攤到o(sqrt(n)),直接暴力更新這個值在這個塊內的資料,然後再暴力更新其他大塊就好了

2.線段樹,直接暴力去懟線段樹就好了

下面是**:

#includeusing namespace std;

const int maxn = 1e4+5;

const int mod = 772002+233;

long long a[maxn],lazy[maxn],num[maxn],ed[maxn];

int n,m;

void updata(int x,long long y)

long long query(int x)

lazy[x+1]+=add,num[x+1]+=num;

return a[x];

}int main()

else

}}

#includeusing namespace std;

const int maxn = 1e5+7;

const int mod = 772002+233;

long long a[maxn];

int l[1000],r[1000];

int block,num,belong[maxn];

long long lazy[maxn],number[maxn],ed[maxn];

int n,m;

void updata(int x,long long y)

for(int i=belong[x]+1;i<=num;i++)

y-=(r[i]-l[i]+1);

}}long long query(int x)

return a[x]%mod;

}int main()

else

}}

#include #include #include #include #include #include #define lid (id << 1)

#define rid (id << 1 | 1)

using namespace std;

typedef long long ll;

const int n = 1e4 + 10;

const ll mod = 772002 + 233;

int n,q;

ll a[n];

struct segtreetr[n * 4];

void segtree_initial(int id,int l,int r)

}void segtree_update(int id,int l,int r,ll x)

int mid = (tr[id].l + tr[id].r) >> 1 ;

segtree_update(lid,l,min(mid , r),x);

segtree_update(rid,max(l , mid + 1),r,x - max(mid + 1 - l , 0) );

}ll segtree_query(int id,int pos)

void init()

void work()

else

}}int main()

#include #define max_n 10004

#define lchild l, m, v << 1

#define rchild m + 1, r, v << 1 | 1

typedef long long ll;

int n, q;

ll a[max_n];

const ll mod = 772002 + 233;

void add(ll &x, ll a)

struct segmenttreetree[max_n * 4];

segmenttree();

void build(int, int, int);

void pushdown(int, int, int);

void update(int, int, ll, int, int, int);

ll query(int, int, int, int);

}seg;

segmenttree::segmenttree()

void segmenttree::build(int l = 1,int r = n, int v = 1)

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

build(lchild);

build(rchild);

}void segmenttree::pushdown(int l, int r, int v)

void segmenttree::update(int l, int r, ll x, int l = 1, int r = n, int v = 1)

if(tree[v].covertime) pushdown(l, r, v);

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

if(l <= m) segmenttree::update(l, r, x, lchild);

if(r > m) segmenttree::update(l, r, x, rchild);

} ll segmenttree::query(int a, int l = 1, int r = n, int v = 1)

int main()

else

printf("%lld\n", seg.query(x));

} return 0;

}

CDOJ 1292 卿學姐種花(分塊)

思路 由於是乙個區間更新問題,而且更新的值不一樣,所以我們考慮分塊。對於乙個塊,我們維護第i塊的第乙個元素被加了多少了sum i 第i塊被更新了多少次cnt i 那麼對於乙個塊內,元素依次增加sum i 遞減cnt i 這是乙個等差數列。細節參見 include include include in...

UESTC 1292 卿學姐種花 (分塊)

題意 給出乙個長度為n的序列,m次操作,操作分為兩種 1.在x的位置上加上數y,在x 1的位置加上數y 1,以此類推,一直到n或者y為0.2.詢問x位置上數字為多少 分析 乍一看像是線段樹,但是貌似又很難用線段樹解決,主要是區間不好處理,而分塊對於這類題目有優勢,在區間上更容易計數,對於每個塊,對於...

CDOJ1329 卿學姐與魔法

附 這道題就是資料結構了 還是比較明顯的優先佇列吧 雖然我想了很久,最後還是看了題解 思路 壓入 a i b 1 最後乙個雙重迴圈拉出佇列 壓入 a i b k k為列舉量 最後佇列裡前n個就是答案 by liucxy include include include include include ...