题目大意
教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。
每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)
CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。
WD巨懒,于是他把这个回答的任务交给了你。
分析
分块。
保证每块是排好序的,查找整块直接二分查找,然后散块暴力修改。
add标记,这样排好序之后查找的话就可以通过二分跳跃很大一部分查找。
一开始二分打错了。。。
数组也开小了。。。
code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
const int maxn=2000000+100;
int a[maxn],b[maxn];
int belong[maxn];
int add[maxn];
int block,cnt;
int l[maxn],r[maxn];
int n,m;
bool cmp(int a,int b)
{
return a>b;
}
int reset(int x)
{
for (int i=l[x];i<=r[x];i++)
{
b[i]=a[i];
}
sort(b+l[x],b+r[x]+1,cmp);
}
int insert(int L,int R,int x)
{
if (belong[L]==belong[R])
{
for (int i=L;i<=R;i++)
a[i]=a[i]+x;
}
else
{
for (int i=L;i<=r[belong[L]];i++)
a[i]=a[i]+x;
for (int i=l[belong[R]];i<=R;i++)
a[i]=a[i]+x;
}
reset(belong[L]); reset(belong[R]);
for (int i=belong[L]+1;i<=belong[R]-1;i++)
add[i]+=x;
}
int find(int x,int rec)
{
int L=l[x];
int R=r[x];
while (L<=R)
{
int mid=(L+R)/2;
if (b[mid]>=rec) L=mid+1;
else R=mid-1;
}
return L-l[x];
}
int answer(int L,int R,int x)
{
int ans=0;
if (belong[L]==belong[R])
{
for (int i=L;i<=R;i++)
if (a[i]+add[belong[i]]>=x) ans++;
return ans;
}
else
{
for (int i=L;i<=r[belong[L]];i++)
if (a[i]+add[belong[i]]>=x) ans++;
for (int i=l[belong[R]];i<=R;i++)
if (a[i]+add[belong[i]]>=x) ans++;
}
for (int i=belong[L]+1;i<=belong[R]-1;i++)
ans+=find(i,x-add[i]);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
block=sqrt(n);
cnt=n/block;
if (n%block) cnt++;
for (int i=1;i<=cnt;i++)
{
l[i]=(i-1)*block+1; r[i]=i*block;
}
r[cnt]=n;
int j=cnt;
for (int i=n;i>0;i--)
{
if (i<l[j]) j--;
belong[i]=j;
}
for (int i=1;i<=cnt;i++)
reset(i);
for (int i=1;i<=m;i++)
{
char c;
int x,y,w;
scanf("\n%c%d%d%d",&c,&x,&y,&w);
if (c=='A')
{
printf("%d\n",answer(x,y,w));
}
else insert(x,y,w);
}
}