教主的魔法
这道题序列很长,但是操作数很少,然后也没想到什么好的数据结构来维护,那就分块吧。
感觉维护的过程很好想,修改的时候对于整个块都在内的直接打标记,两个零散的区间暴力重构,重新排序。查询的时候,对于整块的,直接在块内lowerbound一下z-add[i]的位置,零散的话直接暴力计算即可。
复杂度O(ksqrt(n)logsqrt(n)).注意数组别开小了……
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<set> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') using namespace std; typedef long long ll; const int M = 2000005; const int N = 2005; const ll INF = 1e17+9; const ll mod = 19260817; ll read() { ll ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ans %= mod; ch = getchar(); } return ans * op; } ll a[M],b[N][N],l[N],r[N],blo[M],add[N],n,m,B,cnt,g = 1,x,y,z; char s[5]; ll query(ll x,ll y,ll z) { ll L = blo[x],R = blo[y],ans = 0; if(L == R) { rep(i,x,y) if(a[i] + add[L] >= z) ans++; return ans; } rep(i,L+1,R-1) { //rep(j,1,B) printf("%lld ",b[i][j]);enter; //printf("!%lld\n",z - add[i]); int d = lower_bound(b[i]+1,b[i]+B,z - add[i]) - b[i]; //printf("#%d\n",d); if(d == B && b[i][d] < z - add[i]) continue; ans += B - d + 1; } rep(i,x,r[L]) if(a[i] + add[blo[i]] >= z) ans++; rep(i,l[R],y) if(a[i] + add[blo[i]] >= z) ans++; return ans; } void modify(ll x,ll y,ll z) { ll L = blo[x],R = blo[y],cur = 0; if(L == R) { rep(i,x,y) a[i] += z; rep(i,l[L],r[L]) b[L][++cur] = a[i]; sort(b[L]+1,b[L]+1+B); return; } rep(i,L+1,R-1) add[i] += z; rep(i,x,r[L]) a[i] += z; rep(i,l[R],y) a[i] += z; rep(i,l[L],r[L]) b[L][++cur] = a[i]; sort(b[L]+1,b[L]+B+1),cur = 0; rep(i,l[R],r[R]) b[R][++cur] = a[i]; sort(b[R]+1,b[R]+B+1); } int main() { n = read(),m = read(),B = sqrt(n); cnt = (n % B) ? n / B + 1 : n / B; rep(i,1,cnt) l[i] = r[i-1] + 1,r[i] = l[i] + B - 1; r[cnt] = n; rep(i,1,n) a[i] = read(); rep(i,1,n) { blo[i] = g; if(i == r[g]) g++; } rep(i,1,cnt) { int cur = 0; rep(j,l[i],r[i]) b[i][++cur] = a[j]; sort(b[i]+1,b[i]+B+1); } rep(i,1,m) { scanf("%s",s); x = read(),y = read(),z = read(); if(s[0] == 'A') printf("%lld\n",query(x,y,z)); else modify(x,y,z); } return 0; }
当你意识到,每个上一秒都成为永恒。