本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题意:
给你n个人,每次可以选择两种操作:1、让一段区间中的人身高增长w。2、查询一段区间中身高高于c的人数。
思路:
使用分块算法,用数组b来表示散块每次进行更改后的值,并对其进行排序,查询时查询b数组即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 1e9+7;
#define mem(a,b) memset(a,0,sizeof(a));
ll st[1000100],ed[1000100],a[1000100],b[10000100];
ll sum[1000100],add[1000100],pos[1000100];
void change(ll l,ll r,ll w)
{
ll p = pos[l],q = pos[r];
if(p == q)
{
for(ll i = l; i <= r; i++)
{
a[i] += w;
}
for(ll i = l; i <= r; i++)
b[i] = a[i];
sort(b+l,b+r+1);
}
else
{
for(ll i = p+1; i <= q-1; i++)add[i]+=w;
for(ll i = l; i <= ed[p]; i++)a[i]+=w;
for(ll i = st[p]; i <= ed[p]; i++)b[i] = a[i];
sort(b+st[p],b+ed[p]+1);
for(ll i = st[q]; i <= r; i++)a[i]+=w;
for(ll i = st[q]; i <= ed[q]; i++)b[i] = a[i];
sort(b+st[q],b+ed[q]+1);
}
}
ll ask(ll l,ll r,ll w)
{
ll ans = 0;
ll p = pos[l],q = pos[r];
if(p == q)
{
ans = lower_bound(b+l,b+r,w-add[p])-b;
if(w-add[p] <= b[ans])ans = r-ans+1;
else ans = r-ans;
}
else
{
ll num = 0;
for(ll i = p+1; i <= q-1; i++)
{
num = lower_bound(b+st[i],b+ed[i],w-add[i])-b;
ans += ed[i]-num;
if(w-add[i] <= b[num])ans++;
}
num = lower_bound(b+l,b+ed[p],w-add[p])-b;
ans += ed[p]-num;
if(w-add[p] <= b[num])ans++;
num = lower_bound(b+st[q],b+r,w-add[q])-b;
ans += ed[q]-num;
if(w-add[p] <= b[num])ans++;
}
return ans;
}
int main()
{
ll n,q;
cin>>n>>q;
ll len = sqrt(n);
for(ll i = 1; i <= n; i++)
{
cin>>a[i];
pos[i] = (i-1)/len+1;
sum[(i-1)/len+1]+=a[i];
b[i] = a[i];
}
ll maxx = n%len?n/len+1:n/len;
for(ll i = 1; i <= maxx; i++)
st[i] = (i-1)*len+1,ed[i] = i==maxx?n:i*len;
for(ll i = 1; i <= maxx; i++)
sort(b+st[i], b+ed[i]+1);
while(q--)
{
char op;
scanf(" %c",&op);
if(op == 'M')
{
ll l,r,w;
cin>>l>>r>>w;
change(l,r,w);
}
else
{
ll l,r,w;
cin>>l>>r>>w;
cout<<ask(l,r,w)<<endl;
}
}
}