教主的魔法

传送门

这道题序列很长,但是操作数很少,然后也没想到什么好的数据结构来维护,那就分块吧。

感觉维护的过程很好想,修改的时候对于整个块都在内的直接打标记,两个零散的区间暴力重构,重新排序。查询的时候,对于整块的,直接在块内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;
}

 

posted @ 2018-10-23 08:05  CaptainLi  阅读(191)  评论(0编辑  收藏  举报