3343: 教主的魔法
Time Limit: 10 Sec Memory Limit: 256 MB
Description
教主最近學會了一種神奇的魔法,可以令人長高。因而他準備演示給XMYZ信息組每一個英雄看。因而N個英雄們又一次彙集在了一塊兒,此次他們排成了一列,被編號爲一、二、……、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個英雄身高爲一、二、三、四、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。ios
/*
分塊+二分答案.
對於小塊,暴力搞.
對於整塊打標記,二分查找.
複雜度O(q√nlogn).
(這麼簡單的題怎麼一開始沒想到呢QWQ.
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define MAXN 1000001
using namespace std;
int n,m,q,ans,belong[MAXN],a[MAXN],s[MAXN],tag[MAXN];
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*f;
}
void pre(int x)
{
int l=(x-1)*m+1,r=min(x*m,n);
for(int i=l;i<=r;i++) s[i]=a[i];
sort(s+l,s+r+1);
return ;
}
void change(int x,int y,int z)
{
for(int i=x;i<=min(belong[x]*m,y);i++) a[i]+=z;pre(belong[x]);
if(belong[x]+1<belong[y])// 1 W.
for(int i=belong[x]+1;i<=belong[y]-1;i++) tag[i]+=z;
if(belong[x]!=belong[y])
{
for(int i=(belong[y]-1)*m+1;i<=y;i++) a[i]+=z;
pre(belong[y]);
}
}
int erfen(int x,int z)
{
int l=(x-1)*m+1,r=min(x*m,n);
int p=lower_bound(s+l,s+r+1,z-tag[x])-s;
return r-p+1;
}
void query(int x,int y,int z)
{
ans=0;
for(int i=x;i<=min(belong[x]*m,y);i++)
if(a[i]+tag[belong[i]]>=z) ans++;
if(belong[x]+1<belong[y])
for(int i=belong[x]+1;i<=belong[y]-1;i++) ans+=erfen(i,z);
if(belong[x]!=belong[y])
{
for(int i=(belong[y]-1)*m+1;i<=y;i++)
if(a[i]+tag[belong[i]]>=z) ans++;
}
printf("%d\n",ans);
}
int main()
{
int x,y,z;char ch[3];
n=read(),q=read();
m=sqrt(n);
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) belong[i]=(i-1)/m+1;
for(int i=1;i<=belong[n];i++) pre(i);// 2 w.
while(q--)
{
scanf("%s",ch);x=read(),y=read(),z=read();
if(ch[0]=='M') change(x,y,z);
else query(x,y,z);
}
return 0;
}