fzj2007 @ 2021-12-04 09:47:35
RT。刚刚写了一个非常错误的做法,然后直接过了......
关于这个做法:像题解里面那样块内二分,但是我并没有存下来原来的数组是什么样的,也就是直接对块内进行排序了。
显然,在排序后会打乱块内原有元素的位置,然后暴力分块查询的时候应该出错。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cmath>
#include<iomanip>
#include<string>
#include<cstring>
#include<set>
#include<stack>
#include<queue>
#include<bitset>
using namespace std;
namespace IO{
template<typename T>inline void read(T &x){
x=0;
char ch=getchar();
bool flag=0;
while(ch<'0'||ch>'9') flag=flag||(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+(ch^'0'),ch=getchar();
if(ch!='.'){
x=flag?-x:x;
return;
}
double Base=0.1;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x+Base*(ch^'0'),Base/=10.0,ch=getchar();
x=flag?-x:x;
}
template<typename T>void prt(T x){
if(x>9) prt(x/10);
putchar(x%10+'0');
}
template<typename T>inline void put(char ch,T x){
if(x<0) putchar('-'),x=-x;
prt(x);
putchar(ch);
}
const int DM[10]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
inline void putd(char ch,double x,int w){
if(x<0) putchar('-'),x=-x;
if(!w){
put(ch,(int)(x+0.5));
return;
}
int prex=(int)x;
x-=(int)x;
x*=DM[w];
x+=0.5;
int nowx=(int)x,now=0;
if(nowx>=DM[w]) nowx=0,prex++;
put('.',prex);
int xx=nowx;
if(!xx) now=1;
else while(xx) xx/=10,now++;
now=w-now;
while(now--) putchar('0');
put(ch,nowx);
}
inline void putstr(string s){
for(int i=0;i<s.length();i++) putchar(s[i]);
}
inline bool getch(){
char ch=getchar();
while(ch!='M'&&ch!='A') ch=getchar();
return ch=='M';
}
}
using namespace IO;
#define N 2000005
int n,q,bel[N],L[N],R[N],len,w[N],lg;
int now[N],tag[N];
inline void rebuild(int l,int r,int k){//l~r这个段,断点为k
if(k>r) return;
for(int i=l;i<=r;i++) now[i]=w[i];
int i=l,j=k,t=l;
while(i<k&&j<=r)
if(now[i]>now[j]) w[t++]=now[j++];
else w[t++]=now[i++];
while(i<k) w[t++]=now[i++];
while(j<=r) w[t++]=now[j++];
for(int i=l;i<=r;i++) now[i]=0;
}
inline void update(int l,int r,int num){
int bl=bel[l],br=bel[r];
if(bl==br){
for(int i=l;i<=r;i++) w[i]+=num;
rebuild(L[l],r,l);
rebuild(L[l],R[l],r+1);
return;
}
for(int i=l;i<=R[l];i++) w[i]+=num;
rebuild(L[l],R[l],l);
for(int i=L[r];i<=r;i++) w[i]+=num;
rebuild(L[r],R[r],r+1);
for(int i=bl+1;i<br;i++) tag[i]+=num;
}
inline int query(int l,int r,int k){
int bl=bel[l],br=bel[r],res=0;
if(bl==br){
for(int i=l;i<=r;i++)
res+=(w[i]+tag[bl]>=k);
return res;
}
for(int i=l;i<=R[l];i++) res+=(w[i]+tag[bl]>=k);
for(int i=L[r];i<=r;i++) res+=(w[i]+tag[br]>=k);
for(int i=bl+1;i<br;i++){
int ll=(i-1)*len+1,rr=i*len,lst=i*len+1;
while(ll<=rr){
int mid=ll+rr>>1;
if(tag[i]+w[mid]>=k) rr=mid-1,lst=mid;
else ll=mid+1;
}
res+=i*len-lst+1;
}
return res;
}
int main(){
memset(w,0x3f,sizeof(w));
read(n),read(q);
lg=log(n);
len=sqrt(n*lg)+1;
for(int i=1,beg=1,num=1,id=1;i<=n;i++,num++){
bel[i]=id,L[i]=beg,R[i]=beg+len-1;
if(num==len) num=0,id++,beg=i+1;
}
for(int i=1;i<=n;i++) read(w[i]);
for(int i=1;i<=n;i=R[i]+1) sort(w+L[i],w+R[i]+1);
for(int i=1,op,x,y,c;i<=q;i++){
op=getch(),read(x),read(y),read(c);
if(op) update(x,y,c);
else put('\n',query(x,y,c));
}
return 0;
}
by fzj2007 @ 2021-12-04 09:57:09
加上一组 hack 数据
7 2
9 8 7 6 5 4 3
M 2 3 1
A 2 4 9
正确输出:
1
上面的代码输出
2
by Arctic_1010 @ 2022-02-26 21:41:12
据说 LOJ 数列分块入门 2 这么做也能 AC