洛谷P2801教主的魔法
两种操作:
1.[l,r]所有数加上w
2.询问[l,r]内大于c的个数
解:
询问:整体分块,块内排序,二分查找。
修改:整块修改可以标记保存。此外直接暴力修改。
#define ll long long
const ll N=1e6+5;
ll a[N],id[N],add[N],t[N],size[N];
ll n,q,len;
ll be[N],ed[N];
ll all=0;
void init();
void Sort(ll);
void modify(ll,ll,ll);
ll answer(ll,ll,ll);
void init()//分块
{
len=sqrt(n);
for(ll i=1;i<=len;i++){
be[i]=n/len*(i-1)+1;//begin
ed[i]=n/len*i;//end
}
ed[len]=n;
for(ll i=1;i<=len;i++){
for(ll j=be[i];j<=ed[i];j++)id[j]=i;
size[i]=ed[i]-be[i]+1;
}
for(ll i=1;i<=len;i++)Sort(i);
}
void Sort(ll x)
{
for(ll i=be[x];i<=ed[x];i++)t[i]=a[i];
sort(t+be[x],t+ed[x]+1);
}
void modify(ll l,ll r,ll c)
{
ll lid=id[l],rid=id[r];
if(lid==rid){//same
for(ll i=l;i<=r;i++)a[i]+=c;
Sort(lid);
}
else {//different
for(ll i=l;i<=ed[lid];i++)a[i]+=c;
for(ll i=lid+1;i<rid;i++)add[i]+=c;
for(ll i=be[rid];i<=r;i++)a[i]+=c;
Sort(lid),Sort(rid);
}
return ;
}
ll answer(ll l,ll r,ll c)
{
ll ans=0,lid=id[l],rid=id[r];
if(lid==rid){//same
for(ll i=l;i<=r;i++){
if(a[i]+add[lid]>=c)ans++;
}
return ans;
}
else {//different
for(ll i=l;i<=ed[lid];i++)if(a[i]+add[id[i]]>=c)ans++;
for(ll i=be[rid];i<=r;i++)if(a[i]+add[id[i]]>=c)ans++;
for(ll i=lid+1;i<rid;i++){
ans+=ed[i]-(lower_bound(t+be[i],t+ed[i]+1,c-add[i])-t)+1;//binary search
}
return ans;
}
}
int main()
{
cin>>n>>q;
len=sqrt(n);
for(ll i=1;i<=n;i++){cin>>a[i];}
init();
for(ll k=1;k<=q;k++){
char c;cin>>c;
ll l,r,w;cin>>l>>r>>w;
if(c=='M')modify(l,r,w);
else if(c=='A')cout<<answer(l,r,w)<<'\n';
}
return 0;
}