眾所周知,在喵哈哈村,有乙個溫柔善良的卿學姐。
卿學姐喜歡和她一樣美麗的花。所以卿學姐家的後院有很多的花壇。
卿學姐有\(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 ...