P2801 教主的魔法
这是一道分块好题
显然我们要分块,一开始我们要建立分块,在这里我们要统计的数据有:原序列,每个元素属于哪一个块,每一个块的左右边界,每一个块的lazy,块的总数。
由于这个题目的要求,我们还需要建立一个复制的块来排序,进行查询。
最后不成块元素单独成块。
void build()
{
block=sqrt(n);tot=n/block;
if(n%block) tot++;
for(register int i=1;i<=n;i++){
belong[i]=(i-1)/block+1;d[i]=a[i];
}
for(register int i=1;i<=tot;i++){
L[i]=(i-1)*block+1,R[i]=i*block;
}
R[tot]=n;
for(register int i=1;i<=tot;i++){
sort(d+L[i],d+R[i]+1);
}
}
修改部分:
对于在一个块内的部分,暴力修改
对于不在一个块内的范围,两边暴力修改,中间lazy标记一下
void build()
{
block=sqrt(n);tot=n/block;
if(n%block) tot++;
for(register int i=1;i<=n;i++){
belong[i]=(i-1)/block+1;d[i]=a[i];
}
for(register int i=1;i<=tot;i++){
L[i]=(i-1)*block+1,R[i]=i*block;
}
R[tot]=n;
for(register int i=1;i<=tot;i++){
sort(d+L[i],d+R[i]+1);
}
}
void change()
{
if(belong[x]==belong[y]){
for(register int i=x;i<=y;i++){
a[i]+=k;
}
for(register int i=L[belong[x]];i<=R[belong[x]];i++){
d[i]=a[i];
}
sort(d+L[belong[x]],d+R[belong[x]]+1);
}
else{
for(register int i=x;i<=R[belong[x]];i++){
a[i]+=k;
}
for(register int i=L[belong[x]];i<=R[belong[x]];i++){
d[i]=a[i];
}
sort(d+L[belong[x]],d+R[belong[x]]+1);
for(register int i=L[belong[y]];i<=y;i++){
a[i]+=k;
}
for(register int i=L[belong[y]];i<=R[belong[y]];i++){
d[i]=a[i];
}
sort(d+L[belong[y]],d+R[belong[y]]+1);
for(register int i=belong[x]+1;i<=belong[y]-1;i++){
lazy[i]+=k;
}
}
}
查询:
不成块部分暴力查询,成块部分二分查找
void query()
{
ans=0;
if(belong[x]==belong[y]){
for(register int i=x;i<=y;i++){
if(lazy[belong[x]]+a[i]>=k) ans++;
}
printf("%d\n",ans);
return;
}
else{
for(register int i=x;i<=R[belong[x]];i++){
if(lazy[belong[x]]+a[i]>=k) ans++;
}
for(register int i=L[belong[y]];i<=y;i++){
if(lazy[belong[y]]+a[i]>=k) ans++;
}
for(register int i=belong[x]+1;i<=belong[y]-1;i++){
int ll=L[i],rr=R[i],result=0,mid;
while(ll<=rr)
{
mid=(ll+rr)>>1;
if(d[mid]+lazy[i]>=k)
rr=mid-1,result=R[i]-mid+1;
else
ll=mid+1;
}
ans+=result;
}
printf("%d\n",ans);
}
}
完整部分
#include<bits/stdc++.h>
using namespace std;
int a[1000007],d[1000007],L[1007],R[1007],belong[10000007],lazy[1007],ans;
int n,q,block,tot,x,y,k;
char cz;
template <typename Tp>
void read(Tp &x){
x=0;char ch=1;int fh;
while(ch!='-'&&(ch>'9'||ch<'0')){
ch=getchar();
}
if(ch=='-'){
fh=-1;ch=getchar();
}else fh=1;
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
}
x*=fh;
}
void fr(char &x)
{
x=0;while(x!='M'&&x!='A') x=getchar();
}
void build()
{
block=sqrt(n);tot=n/block;
if(n%block) tot++;
for(register int i=1;i<=n;i++){
belong[i]=(i-1)/block+1;d[i]=a[i];
}
for(register int i=1;i<=tot;i++){
L[i]=(i-1)*block+1,R[i]=i*block;
}
R[tot]=n;
for(register int i=1;i<=tot;i++){
sort(d+L[i],d+R[i]+1);
}
}
void change()
{
if(belong[x]==belong[y]){
for(register int i=x;i<=y;i++){
a[i]+=k;
}
for(register int i=L[belong[x]];i<=R[belong[x]];i++){
d[i]=a[i];
}
sort(d+L[belong[x]],d+R[belong[x]]+1);
}
else{
for(register int i=x;i<=R[belong[x]];i++){
a[i]+=k;
}
for(register int i=L[belong[x]];i<=R[belong[x]];i++){
d[i]=a[i];
}
sort(d+L[belong[x]],d+R[belong[x]]+1);
for(register int i=L[belong[y]];i<=y;i++){
a[i]+=k;
}
for(register int i=L[belong[y]];i<=R[belong[y]];i++){
d[i]=a[i];
}
sort(d+L[belong[y]],d+R[belong[y]]+1);
for(register int i=belong[x]+1;i<=belong[y]-1;i++){
lazy[i]+=k;
}
}
}
void query()
{
ans=0;
if(belong[x]==belong[y]){
for(register int i=x;i<=y;i++){
if(lazy[belong[x]]+a[i]>=k) ans++;
}
printf("%d\n",ans);
return;
}
else{
for(register int i=x;i<=R[belong[x]];i++){
if(lazy[belong[x]]+a[i]>=k) ans++;
}
for(register int i=L[belong[y]];i<=y;i++){
if(lazy[belong[y]]+a[i]>=k) ans++;
}
for(register int i=belong[x]+1;i<=belong[y]-1;i++){
int ll=L[i],rr=R[i],result=0,mid;
while(ll<=rr)
{
mid=(ll+rr)>>1;
if(d[mid]+lazy[i]>=k)
rr=mid-1,result=R[i]-mid+1;
else
ll=mid+1;
}
ans+=result;
}
printf("%d\n",ans);
}
}
int mian()
{
read(n);read(q);
for(register int i=1;i<=n;i++)
read(a[i]);
build();
while(q--){
fr(cz);
read(x);read(y);read(k);
if(cz=='M'){
change();
}
if(cz=='A'){
query();
}
}
return 0;
}