[bzoj3343] 教主的魔法

Description

教主最近學會了一種神奇的魔法,可以令人長高。因而他準備演示給XMYZ信息組每一個英雄看。因而 N個英雄們又一次彙集在了一塊兒,此次他們排成了一列,被編號爲一、二、……、 N
每一個人的身高一開始都是不超過1000的正整數。教主的魔法每次能夠把閉區間[ LR](1≤ LRN)內的英雄的身高所有加上一個整數 W。(雖然 L= R時並不符合區間的書寫規範,但咱們能夠認爲是單獨增長第 LR)個英雄的身高)
CYZ、光哥和ZJQ等人不信教主的邪,因而他們有時候會問WD閉區間 [ LR] 內有多少英雄身高大於等於 C,以驗證教主的魔法是否真的有效。
WD巨懶,因而他把這個回答的任務交給了你。

Input

       第1行爲兩個整數 NQQ爲問題數與教主的施法數總和。
       第2行有 N個正整數,第 i個數表明第 i個英雄的身高。
       第3到第 Q+2行每行有一個操做:
(1)       若第一個字母爲「M」,則緊接着有三個數字 LRW。表示對閉區間 [ LR] 內全部英雄的身高加上 W
(2)       若第一個字母爲「A」,則緊接着有三個數字 LRC。詢問閉區間 [ LR] 內有多少英雄的身高大於等於 C

Output

       對每一個「A」詢問輸出一行,僅含一個整數,表示閉區間 [ LR] 內身高大於等於 C的英雄數。

Sample Input

5 3
1 2 3 4 5
A 1 5 4
M 3 5 1
A 1 5 4

Sample Output

2
3

HINT

【輸入輸出樣例說明】
原先5個英雄身高爲一、二、三、四、5,此時[1, 5]間有2個英雄的身高大於等於4。教主施法後變爲一、二、四、五、6,此時[1, 5]間有3個英雄的身高大於等於4。
【數據範圍】
對30%的數據, N≤1000, Q≤1000。
對100%的數據, N≤1000000, Q≤3000,1≤ W≤1000,1≤ C≤1,000,000,000。

思路

分塊,分紅根n塊,對於每一個塊,構建一個映射數組,轉移原數組值,並排序,還有一個標記,儲存增值;
對於每次增值操做,對於整塊,直接修改標記,對於非整塊,暴力修改原數組,並從新構建映射數組;
對於每次查詢操做,對於整塊,直接在映射數組中二分,對於非整塊,暴力枚舉;

代碼實現

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<algorithm>
 4 const int maxn=1e6+10;
 5 const int maxm=1e3+10;
 6 int n,m,p;
 7 int s[maxn];
 8 int t[maxn],f[maxm];
 9 int search(int l,int r,int x){
10     int ret=0;
11     for(int i=l;i<=r;i++) if(s[i]>=x) ret++;
12     return ret;
13 }
14 int find(int l,int r,int x){
15     int mid,a=r;
16     while(l!=r){
17         mid=l+r>>1;
18         if(t[mid]<x) l=mid+1;
19         else r=mid;
20     }
21     if(t[l]<x) l++;
22     return a-l+1;
23 }
24 void map(int l,int r){
25     for(int i=l;i<=r;i++) t[i]=s[i];
26     std::sort(t+l,t+r+1);
27 }
28 void add(int l,int r,int x){
29     for(int i=l;i<=r;i++) s[i]+=x;
30     map((l-1)/p*p+1,(r+p-1)/p*p);
31 }
32 int main(){
33     scanf("%d%d",&n,&m),p=sqrt(n);
34     for(int i=1;i<=n;i++) scanf("%d",&s[i]);
35     for(int i=1;i<=n/p;i++) map((i-1)*p+1,i*p);
36     if(n%p) map(n/p*p+1,n);
37     int l,r,x,ans;char ch[3];
38     while(m--){
39         scanf("%s%d%d%d",ch,&l,&r,&x);
40         if(ch[0]=='M'){
41             if((l-1)/p==(r-1)/p){add(l,r,x);continue;}
42             if(l%p!=1) add(l,((l-1)/p+1)*p,x);
43             for(int i=(l+1)/p+1;i<=r/p;i++) f[i]+=x;
44             if(r%p) add(r/p*p+1,r,x);
45         }
46         if(ch[0]=='A'){
47             ans=0;
48             if((l-1)/p==(r-1)/p) ans+=search(l,r,x-f[(r-1)/p+1]);
49             else{
50                 if(l%p!=1) ans+=search(l,((l-1)/p+1)*p,x-f[(l-1)/p+1]);
51                 for(int i=(l+1)/p+1;i<=r/p;i++) ans+=find((i-1)*p+1,i*p,x-f[i]);
52                 if(r%p!=0) ans+=search(r/p*p+1,r,x-f[r/p+1]);
53             }
54             printf("%d\n",ans);
55         }
56     }
57     return 0;
58 }

emmmmm,這題數據彷佛很是水,反正我和洛谷裏嘉諾巨型方塊小數據都拍不過QUQ(固然是他們錯啦:P)數組

順便,這是我第一次寫分塊,我真的太弱了QUQspa

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息