Description
教主最近學會了一種神奇的魔法,能夠使人長高。於是他準備演示給XMYZ信息組每個英雄看。於是N個英雄們又一次聚集在了一起,這次他們排成了一列,被編號爲1、2、……、N。
每個人的身高一開始都是不超過1000的正整數。教主的魔法每次可以把閉區間[L, R](1≤L≤R≤N)內的英雄的身高全部加上一個整數W。(雖然L=R時並不符合區間的書寫規範,但我們可以認爲是單獨增加第L(R)個英雄的身高)
CYZ、光哥和ZJQ等人不信教主的邪,於是他們有時候會問WD閉區間 [L, R] 內有多少英雄身高大於等於C,以驗證教主的魔法是否真的有效。
WD巨懶,於是他把這個回答的任務交給了你。
Input
第1行爲兩個整數N、Q。Q爲問題數與教主的施法數總和。
第2行有N個正整數,第i個數代表第i個英雄的身高。
第3到第Q+2行每行有一個操作:
(1) 若第一個字母爲“M”,則緊接着有三個數字L、R、W。表示對閉區間 [L, R] 內所有英雄的身高加上W。
(2) 若第一個字母爲“A”,則緊接着有三個數字L、R、C。詢問閉區間 [L, R] 內有多少英雄的身高大於等於C。
Output
對每個“A”詢問輸出一行,僅含一個整數,表示閉區間 [L, R] 內身高大於等於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個英雄身高爲1、2、3、4、5,此時[1, 5]間有2個英雄的身高大於等於4。教主施法後變爲1、2、4、5、6,此時[1, 5]間有3個英雄的身高大於等於4。
【數據範圍】
對30%的數據,N≤1000,Q≤1000。
對100%的數據,N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000。
Solution
分塊可以做,然而花式分塊更快。。
在每個操作的端點處劃分,共分爲最多4Q塊,那麼每個操作必會在一段連續塊上
處理每塊時,遍歷所有包含它的操作,若爲修改,則delta+=w,若爲查詢,則記錄c-delta,然後將詢問按c-delta排序
之後遍歷該塊中的數,二分+差分維護貢獻
時間複雜度
Code
#include<bits/stdc++.h>
typedef unsigned char uchar;
typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
#define xx first
#define yy second
template<typename T> inline T max(T a,T b){return a>b?a:b;}
template<typename T> inline T min(T a,T b){return a<b?a:b;}
template<typename T> inline T abs(T a){return a>0?a:-a;}
template<typename T> inline void repr(T &a,T b){if(a<b)a=b;}
template<typename T> inline void repl(T &a,T b){if(a>b)a=b;}
template<typename T> T gcd(T a,T b){if(b)return gcd(b,a%b);return a;}
#define mp(a,b) std::make_pair(a,b)
#define pb push_back
#define lb(x) ((x)&(-(x)))
#define sqr(x) ((x)*(x))
#define pm(a,b,c,d) a=(a+(ll)(b)*(c))%(d)
int n,m,h[1000001],q[3000][4],bl[12010],ans[3000],tmp[3000];
struct yjq
{
int x,id;
inline bool operator <(const yjq &p)const
{
return x<p.x;
}
}f[3000];
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",h+i);
int bc=2;
bl[0]=n-1;
bl[1]=-1;
for(int i=0;i<m;i++)
{
char opt[2];
scanf("%s%d%d%d",opt,&q[i][1],&q[i][2],&q[i][3]);
q[i][1]--,q[i][2]--;
q[i][0]=opt[0]=='A';
bl[bc++]=q[i][1]-1;
bl[bc++]=q[i][2];
}
std::sort(bl,bl+bc);
bc=std::unique(bl,bl+bc)-bl;
for(int i=1;i<bc;i++)
{
bl[i-1]++;
int delta=0,fm=0;
for(int j=0;j<m;j++)
if(q[j][1]<=bl[i-1]&&q[j][2]>=bl[i])
{
if(q[j][0]==0)
delta+=q[j][3];
else
f[fm].x=q[j][3]-delta,f[fm++].id=j;
}
std::sort(f,f+fm);
memset(tmp,0,sizeof(tmp));
for(int j=bl[i-1];j<=bl[i];j++)
{
if(f[0].x>h[j])continue;
int l=0,r=fm;
while(r-l>1)
{
if(f[(l+r)>>1].x>h[j])
r=(l+r)>>1;
else
l=(l+r)>>1;
}
tmp[l]++;
}
for(int j=fm-1,t=0;j>=0;j--)
{
t+=tmp[j];
ans[f[j].id]+=t;
}
}
for(int i=0;i<m;i++)
if(q[i][0]==1)
printf("%d\n",ans[i]);
}