数列分块入门训练集:
入门2:
求出小于每个数的个数,维持块内有序,进行二分。
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<ll,int>P;
const int N=5e4+5;
vector<ll>v[N];
int L[N],R[N],belong[N];
ll d[N],lazy[N];
int block,num;
void read(int &x)
{
x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
x*=f;
}
void solve(int p)
{
v[p].clear();
for(int i=L[p];i<=R[p];i++)
v[p].pb(d[i]);
sort(v[p].begin(),v[p].end());
}
void build(int n)
{
block=sqrt(n);
num=n/block;
if(n%block)
num++;
for(int i=1;i<=num;i++)
L[i]=(i-1)*block+1,R[i]=block*i;
R[num]=n;
for(int i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
memset(lazy,0,sizeof(lazy));
}
void update(int l,int r,int c)
{
int p=belong[l];
int q=belong[r];
if(p==q)
{
for(int i=l;i<=r;i++)
d[i]+=c;
solve(p);
}
else
{
for(int i=p+1;i<q;i++)
lazy[i]+=c;
for(int i=l;i<=R[p];i++)
d[i]+=c;
solve(p);
for(int i=L[q];i<=r;i++)
d[i]+=c;
solve(q);
}
}
int query(int l,int r,int c)
{
ll t=1LL*c*c;
int res=0,p=belong[l],q=belong[r];
if(p==q)
{
for(int i=l;i<=r;i++)
{
if(d[i]<t-lazy[p])
res++;
}
}
else
{
for(int i=p+1;i<q;i++)
{
int m=lower_bound(v[i].begin(),v[i].end(),t-lazy[i])-v[i].begin();
res+=m;
}
for(int i=l;i<=R[p];i++)
{
if(d[i]<t-lazy[p])
res++;
}
for(int i=L[q];i<=r;i++)
{
if(d[i]<t-lazy[q])
res++;
}
}
return res;
}
int main()
{
int n,x;
read(n);
build(n);
for(int i=1;i<=n;i++)
{
read(x);
d[i]=x;
v[belong[i]].pb(x);
}
for(int i=1;i<=num;i++)
sort(v[i].begin(),v[i].end());
int op,l,r,c;
for(int i=1;i<=n;i++)
{
read(op);
read(l);
read(r);
read(c);
if(op==0)
update(l,r,c);
else
printf("%d
",query(l,r,c));
}
return 0;
}
楼房重建 HYSBZ - 2957:
分析:
维护每个块的最大斜率值和块内呈递增的高度序列,每次更新时,重新维护序列。
复杂度:(O(m*(sqrt{n}+num*log(sqrt{n}))))
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=1e5+5;
const int maxn=1005;
double hm[maxn],h[N];
vector<double>v[maxn];
int block,num;
int belong[N],L[maxn],R[maxn];
void build(int n)
{
block=sqrt(n);
num=n/block;
if(n%block)
num++;
for(int i=1;i<=num;i++)
{
L[i]=(i-1)*block+1;
R[i]=i*block;
}
R[num]=n;
for(int i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
}
void update(int x,int y)
{
int p=belong[x];
v[p].clear();
h[x]=1.0*y/x;
double m=0;
for(int i=L[p];i<=R[p];i++)
{
if(h[i]>m)
{
v[p].pb(h[i]);
m=h[i];
}
}
hm[p]=m;
}
int query()
{
int res=0;
double m=0;
for(int i=1;i<=num;i++)
{
int t=upper_bound(v[i].begin(),v[i].end(),m)-v[i].begin();
res+=(v[i].size()-t);
if(hm[i]>m)//注意
m=hm[i];
}
return res;
}
int main()
{
int n,m,x,y;
scanf("%d%d",&n,&m);
build(n);
while(m--)
{
scanf("%d%d",&x,&y);
update(x,y);
printf("%d
",query());
}
return 0;
}