东郭 @ 2020-07-29 08:17:33
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int n,m,num,a[1000001],b[1000001],bel[1000001],l[10001],r[10001],flag[10001];
inline void change(int x){
for(int i=l[bel[x]];i<=r[bel[x]];i++)b[i]=a[i];
sort(b+l[bel[x]],b+r[bel[x]]+1);
return;
}
inline void update(int x,int y,int z){
if(bel[x]==bel[y]){
for(int i=x;i<=y;i++)a[i]+=z;
change(x);
return;
}
for(int i=x;i<=r[bel[x]];i++)a[i]+=z;
for(int i=l[bel[y]];i<=y;i++)a[i]+=z;
change(x);change(y);
for(int i=bel[x]+1;i<=bel[y]-1;i++)flag[i]+=z;
return;
}
inline int find(int x,int y,int z){
while(x<=y){
int mid=(x+y)>>1;
if(b[mid]<z) x=mid+1;
else y=mid-1;
}
return y;
}
inline int query(int x,int y,int z){
int ans=0;
if(bel[x]==bel[y]){
for(int i=x;i<=y;i++)
if(a[i]+flag[bel[x]]>=z)
ans++;
return ans;
}
for(int i=x;i<=r[bel[x]];i++)
if(a[i]+flag[bel[x]]>=z)
ans++;
for(int i=l[bel[y]];i<=y;i++)
if(a[i]+flag[bel[y]]>=z)
ans++;
for(int i=bel[x]+1;i<=bel[y]-1;i++)
ans+=r[i]-find(l[i],r[i],z-flag[bel[i]])+1;
return ans;
}
int main(){
num=sqrt(n);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=num;i++) l[i]=r[i-1]+1,r[i]=i*num;
if(r[num]<n) num++,l[num]=r[num-1]+1,r[num]=n;
for(int i=1;i<=num;i++)
for(int j=l[i];j<=r[i];j++)
bel[j]=i,b[j]=a[j];
for(int i=1;i<=num;i++)
sort(b+l[i],b+r[i]+1);
char lon[3];
int x1,x2,x3;
while(m--){
cin>>lon;
scanf("%d%d%d",&x1,&x2,&x3);
if(lon[0]=='A') printf("%d\n",query(x1,x2,x3));
else update(x1,x2,x3);
}
return 0;
}
时间复杂度与题解一样,TLE了5,6,7,8,10五个点。
by 东郭 @ 2020-07-29 08:20:50
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int n,m,num,a[1000001],b[1000001],bel[1000001],l[10001],r[10001],flag[10001];
inline void change(int x){
for(int i=l[bel[x]];i<=r[bel[x]];i++)b[i]=a[i];
sort(b+l[bel[x]],b+r[bel[x]]+1);
return;
}
inline void update(int x,int y,int z){
if(bel[x]==bel[y]){
for(int i=x;i<=y;i++)a[i]+=z;
change(x);
return;
}
for(int i=x;i<=r[bel[x]];i++)a[i]+=z;
for(int i=l[bel[y]];i<=y;i++)a[i]+=z;
change(x);change(y);
for(int i=bel[x]+1;i<=bel[y]-1;i++)flag[i]+=z;
return;
}
inline int find(int x,int y,int z){
while(x<=y){
int mid=(x+y)>>1;
if(b[mid]<z) x=mid+1;
else y=mid-1;
}
return y;
}
inline int query(int x,int y,int z){
int ans=0;
if(bel[x]==bel[y]){
for(int i=x;i<=y;i++)
if(a[i]+flag[bel[x]]>=z)
ans++;
return ans;
}
for(int i=x;i<=r[bel[x]];i++)
if(a[i]+flag[bel[x]]>=z)
ans++;
for(int i=l[bel[y]];i<=y;i++)
if(a[i]+flag[bel[y]]>=z)
ans++;
for(int i=bel[x]+1;i<=bel[y]-1;i++)
ans+=r[i]-find(l[i],r[i],z-flag[bel[i]])+1;
return ans;
}
int main(){
scanf("%d%d",&n,&m);
num=sqrt(n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=num;i++) l[i]=r[i-1]+1,r[i]=i*num;
if(r[num]<n) num++,l[num]=r[num-1]+1,r[num]=n;
for(int i=1;i<=num;i++)
for(int j=l[i];j<=r[i];j++)
bel[j]=i,b[j]=a[j];
for(int i=1;i<=num;i++)
sort(b+l[i],b+r[i]+1);
char lon[3];
int x1,x2,x3;
while(m--){
cin>>lon;
scanf("%d%d%d",&x1,&x2,&x3);
if(lon[0]=='A') printf("%d\n",query(x1,x2,x3));
else update(x1,x2,x3);
}
return 0;
}
WA九个点
by Lidozs55 @ 2020-07-29 08:24:10
宁先试试O2?
话说我也不太清楚
by 东郭 @ 2020-07-29 08:28:24
O2也没过。
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int n,m,num,a[1000001],b[1000001],bel[1000001],l[10001],r[10001],flag[10001];
inline void change(int x){
for(int i=l[bel[x]];i<=r[bel[x]];i++)b[i]=a[i];
sort(b+l[bel[x]],b+r[bel[x]]+1);
return;
}
inline void update(int x,int y,int z){
if(bel[x]==bel[y]){
for(int i=x;i<=y;i++)a[i]+=z;
change(x);
return;
}
for(int i=x;i<=r[bel[x]];i++)a[i]+=z;
for(int i=l[bel[y]];i<=y;i++)a[i]+=z;
change(x);change(y);
for(int i=bel[x]+1;i<=bel[y]-1;i++)flag[i]+=z;
return;
}
inline int find(int x,int y,int z){
while(x<y){
int mid=(x+y)>>1;
if(b[mid]<z) x=mid+1;
else y=mid-1;
}
return y;
}
inline int query(int x,int y,int z){
int ans=0;
if(bel[x]==bel[y]){
for(int i=x;i<=y;i++)
if(a[i]+flag[bel[x]]>=z)
ans++;
return ans;
}
for(int i=x;i<=r[bel[x]];i++)
if(a[i]+flag[bel[x]]>=z)
ans++;
for(int i=l[bel[y]];i<=y;i++)
if(a[i]+flag[bel[y]]>=z)
ans++;
for(int i=bel[x]+1;i<=bel[y]-1;i++)
ans+=r[i]-find(l[i],r[i],z-flag[i])+1;
return ans;
}
int main(){
memset(flag,0,sizeof flag);
scanf("%d%d",&n,&m);
num=sqrt(n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=num;i++) l[i]=r[i-1]+1,r[i]=i*(n/num);
if(r[num]<n) num++,l[num]=r[num-1]+1,r[num]=n;
for(int i=1;i<=num;i++)
for(int j=l[i];j<=r[i];j++)
bel[j]=i,b[j]=a[j];
for(int i=1;i<=num;i++)
sort(b+l[i],b+r[i]+1);
char lon[3];
int x1,x2,x3;
while(m--){
cin>>lon;
scanf("%d%d%d",&x1,&x2,&x3);
if(lon[0]=='A') printf("%d\n",query(x1,x2,x3));
else update(x1,x2,x3);
}
return 0;
}
by _蒟蒻—信含_ @ 2020-07-29 08:42:51
for太多?这for多的(逃
by 东郭 @ 2020-07-29 08:44:00
主要是二分的锅
by _蒟蒻—信含_ @ 2020-07-29 08:45:02
@东郭 rxz的二分只有两行for主要是递归
by _蒟蒻—信含_ @ 2020-07-29 08:46:05
这题看不太懂你看我菜的连勾勾都没
by Anonymous_U @ 2020-07-29 08:59:29
把二分里while(x<y),改成while(x<=y) 把ans+=r[i]-find(l[i],r[i],z-flag[i])+1; 改成ans+=r[i]-find(l[i],r[i],z-flag[i]);
by Anonymous_U @ 2020-07-29 08:59:59
亲测能过
by 东郭 @ 2020-07-29 09:12:21
谢谢巨佬