题解:分块。用vector维护每个块,二分查找。及时更新边块即可。当前值+此块增加的值<c*c,即当前值<c*c-块同时增加的值。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int w[maxn],n,block,cnt,sum[maxn];
vector<int> v[50005];
int get(int x);
void update(int l,int r,int c);
int check(int l,int r,int c);
void reset(int k);
int main()
{
int i,op,l,r,c;
scanf("%d",&n);
block=sqrt(n);
if(n%block) cnt=n/block+1;
else cnt=n/block;
for(i=1;i<=n;i++)
{
scanf("%d",&w[i]);
v[get(i)].push_back(w[i]);
}
for(i=1;i<=cnt;i++) sort(v[i].begin(),v[i].end());
for(i=0;i<n;i++)
{
scanf("%d%d%d%d",&op,&l,&r,&c);
if(op==0) update(l,r,c);
else printf("%d
",check(l,r,c*c));
}
system("pause");
return 0;
}
int get(int x)
{return (x-1)/block+1;}
void reset(int k)
{
v[k].clear();
for(int i=(k-1)*block+1;i<=min(k*block,n);i++) v[k].push_back(w[i]);
sort(v[k].begin(),v[k].end());
}
void update(int l,int r,int c)
{
int pre,end,k;
pre=get(l);end=get(r);
if(pre==end)
{
for(k=l;k<=r;k++) w[k]+=c;
reset(pre);
}
else
{
for(k=l;k<=min(pre*block,n);k++) w[k]+=c;
for(k=(end-1)*block+1;k<=r;k++) w[k]+=c;
for(k=pre+1;k<end;k++) sum[k]+=c;
reset(pre);reset(end);
}
}
int check(int l,int r,int c)
{
int ans=0,pre,end,k,x;
pre=get(l);end=get(r);
if(pre==end)
{
for(k=l;k<=r;k++)
if(w[k]+sum[pre]<c) ans++;
}
else
{
for(k=l;k<=min(pre*block,n);k++) if(w[k]+sum[get(k)]<c) ans++;
for(k=(end-1)*block+1;k<=r;k++) if(w[k]+sum[get(k)]<c) ans++;
for(k=pre+1;k<end;k++)
{
x=c-sum[k];
ans+=lower_bound(v[k].begin(),v[k].end(),x)-v[k].begin();
}
}
return ans;
}
题解:分块。与数列分块入门 2类似,稍微修改即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int w[maxn],n,block,cnt,sum[maxn];
vector<int> v[50005];
int get(int x);
void update(int l,int r,int c);
int check(int l,int r,int c);
void reset(int k);
int main()
{
int i,op,l,r,c;
scanf("%d",&n);
block=sqrt(n);
if(n%block) cnt=n/block+1;
else cnt=n/block;
for(i=1;i<=n;i++)
{
scanf("%d",&w[i]);
v[get(i)].push_back(w[i]);
}
for(i=1;i<=cnt;i++) sort(v[i].begin(),v[i].end());
for(i=0;i<n;i++)
{
scanf("%d%d%d%d",&op,&l,&r,&c);
if(op==0) update(l,r,c);
else printf("%d
",check(l,r,c));
}
system("pause");
return 0;
}
int get(int x)
{return (x-1)/block+1;}
void reset(int k)
{
v[k].clear();
for(int i=(k-1)*block+1;i<=min(k*block,n);i++) v[k].push_back(w[i]);
sort(v[k].begin(),v[k].end());
}
void update(int l,int r,int c)
{
int pre,end,k;
pre=get(l);end=get(r);
if(pre==end)
{
for(k=l;k<=r;k++) w[k]+=c;
reset(pre);
}
else
{
for(k=l;k<=min(pre*block,n);k++) w[k]+=c;
for(k=(end-1)*block+1;k<=r;k++) w[k]+=c;
for(k=pre+1;k<end;k++) sum[k]+=c;
reset(pre);reset(end);
}
}
int check(int l,int r,int c)
{
int ans=-0x3f3f3f3f,pre,end,k,x,flag=0;
pre=get(l);end=get(r);
if(pre==end)
{
for(k=l;k<=r;k++)
{
if(w[k]+sum[pre]<c)
{
flag=1;
ans=max(ans,w[k]+sum[pre]);
}
}
}
else
{
for(k=l;k<=min(pre*block,n);k++)
if(w[k]+sum[get(k)]<c)
flag=1,ans=max(ans,w[k]+sum[get(k)]);
for(k=(end-1)*block+1;k<=r;k++)
if(w[k]+sum[get(k)]<c)
flag=1,ans=max(ans,w[k]+sum[get(k)]);
for(k=pre+1;k<end;k++)
{
x=c-sum[k];
int index=lower_bound(v[k].begin(),v[k].end(),x)-v[k].begin();
if(index>0&&v[k][index-1]+sum[k]<c)
flag=1,ans=max(ans,v[k][index-1]+sum[k]);
}
}
return flag==1?ans:-1;
}