思路:虽然n很大,但是查询次数Q有限,只有3000,左右,因此我们可以用分块算法解决该题,通过vector将每一块变成一个有序的块,在每次更新操作,直接暴力更新即可。
#include<set> #include<queue> #include<vector> #include<string> #include<math.h> #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; #define maxn 1000050 #define SQ 1005 #define ll long long int mark[SQ],size[SQ]; int n,m,a[maxn],sq; int st[SQ],ed[SQ],bel[maxn]; vector<int> arr[SQ]; int read() { int ans = 0; char c = getchar(); while (!isdigit(c)) c = getchar(); while (isdigit(c)) { ans = ans * 10 + c - '0'; c = getchar(); } return ans; } void init(int n){ sq=sqrt(n); for(int i=1;i<=sq;i++){ st[i]=n/sq*(i-1)+1; ed[i]=n/sq*i; } ed[sq]=n; for(int i=1;i<=sq;i++){ for(int j=st[i];j<=ed[i];j++) bel[j]=i; size[i]=ed[i]-st[i]+1; } } void update(int index){ for(int i=0;i<size[index];i++) arr[index][i]=a[st[index]+i]; sort(arr[index].begin(),arr[index].end()); } int main(void){ int x,y,z; n=read(); m=read(); init(n); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=sq;i++) for(int j=st[i];j<=ed[i];j++) arr[i].push_back(a[j]); for(int i=1;i<=sq;i++) sort(arr[i].begin(),arr[i].end()); while(m--){ char c; scanf(" %c",&c); x=read(); y=read(); z=read(); if(c=='M'){ if(bel[x]==bel[y]){ for(int i=x;i<=y;i++) a[i]+=z; update(bel[x]); continue; } for(int i=x;i<=ed[bel[x]];i++) a[i]+=z; for(int i=st[bel[y]];i<=y;i++) a[i]+=z; update(bel[x]); update(bel[y]); for(int i=bel[x]+1;i<bel[y];i++) mark[i]+=z; } else{ int tot=0; if(bel[x]==bel[y]){ for(int i=x;i<=y;i++){ if(a[i]+mark[bel[x]]>=z) tot++; } printf("%d\n",tot); continue; } for(int i=x;i<=ed[bel[x]];i++) if(a[i]+mark[bel[x]]>=z) tot++; for(int i=st[bel[y]];i<=y;i++) if(a[i]+mark[bel[y]]>=z) tot++; for(int i=bel[x]+1;i<bel[y];i++) tot+=arr[i].end()-lower_bound(arr[i].begin(),arr[i].end(),z-mark[i]); printf("%d\n",tot); } } return 0; }