loj数列分块入门(上)

简介: 数列分块入门入门 1-区间加法-单点查询入门 2-区间加法-区间查询入门 3-区间加法-单点查询入门 4-区间加法-区间查询入门 5-区间开方-区间查询

数列分块入门


入门 1-区间加法-单点查询


24ff5589ce924a7fb8647f805a4c99ad.png

ll n,a[maxn],lazy[maxn];
int main() {
  n = read;
  for(int i=1; i<=n; i++) a[i] = read;
  int blk = sqrt(n);
  for(int ii=1; ii<=n; ii++) {
    int op = read,l = read,r = read,c = read;
    if( op == 0) {
      for(int i=l; i<min(r+1,(l/blk+1)*blk); i++) {
        a[i] += c;
      }
      for(int i=l/blk+1; i<r/blk; i++) {
        lazy[i] += c;
      }
      if(l / blk != r / blk) {
        for(int i=r/blk*blk; i<=r; i++) a[i] += c;
      }
    } else {
      printf("%lld\n",a[r] + lazy[r/blk]);
    }
  }
  return 0;
}
/**
4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0
2
5
**/


入门 2-区间加法-区间查询


6e6026e88daa4d39957b647b1985ca54.png

const int maxn = 1e5 + 7;
ll n, a[maxn];
vector<ll> vet[maxn];
ll blk, lazy[maxn], b[maxn];
void reget(int id) {
    vet[id].clear();
    for (int i = (id - 1) * blk + 1; i <= min(n, id * blk); i++) {
        vet[id].push_back(a[i]);
    }
    sort(vet[id].begin(), vet[id].end());
}
void update(ll l, ll r, ll c) {
    for (int i = l; i <= min(b[l]*blk, r); i++)
        a[i] += c;
    reget(b[l]);
    if (b[l] != b[r]) {
        for (int i = (b[r] - 1) * blk + 1; i <= r; i++)
            a[i] += c;
        reget(b[r]);
    }
    for (int i = b[l] + 1; i <= b[r] - 1; i++) {
        lazy[i] += c;
    }
}
ll query(ll l, ll r, ll val) {
    ll ret = 0;
    for (int i = l; i <= min(b[l]*blk, r); i++) {
        if (a[i] + lazy[b[l]] < val)
            ++ ret;
    }
    if (b[l] != b[r]) {
        for (int i = (b[r] - 1) * blk + 1; i <= r; i++) {
            if (a[i] + lazy[b[r]] < val)
                ++ ret;
        }
    }
    for (int i = b[l] + 1; i <= b[r] - 1; i++) {
        int get = val - lazy[i];
        //      ret += upper_bound(vet[i].begin(),vet[i].end(),get) - lower_bound(vet[i].begin(),vet[i].end(),get);
        ret += lower_bound(vet[i].begin(), vet[i].end(), get) - vet[i].begin();
    }
    return ret;
}
int main() {
    n = read;
    for (int i = 1; i <= n; i++)
        a[i] = read;
    blk = sqrt(n);
    for (int i = 1; i <= n; i++) {
        b[i] = (i - 1) / blk + 1;
        vet[b[i]].push_back(a[i]);
    }
    for (int i = 1; i <= b[n]; i++)
        sort(vet[i].begin(), vet[i].end());
    for (int i = 1; i <= n; i++) {
        int op = read, l = read, r = read, c = read;
        if (op == 0)
            update(l, r, c);
        else
            printf("%lld\n", query(l, r, c * c));
    }
    return 0;
}
/**
4
1 2 2 3
0 1 3 1
1 1 3 2
1 1 4 1
1 2 3 2
3
0
2
**/


入门 3-区间加法-单点查询


86d3ffebdebe4a449b65d5b8897be280.png


const int maxn = 1e5 + 7;
ll n, a[maxn];
vector<ll> vet[maxn];
ll blk, lazy[maxn], b[maxn];
void reget(int id) {
    vet[id].clear();
    for (int i = (id - 1) * blk + 1; i <= min(n, id * blk); i++) {
        vet[id].push_back(a[i]);
    }
    sort(vet[id].begin(), vet[id].end());
}
void update(ll l, ll r, ll c) {
    for (int i = l; i <= min(b[l]*blk, r); i++)
        a[i] += c;
    reget(b[l]);
    if (b[l] != b[r]) {
        for (int i = (b[r] - 1) * blk + 1; i <= r; i++)
            a[i] += c;
        reget(b[r]);
    }
    for (int i = b[l] + 1; i <= b[r] - 1; i++) {
        lazy[i] += c;
    }
}
ll query(ll l, ll r, ll val) {
    ll ret = -1;
    for (int i = l; i <= min(b[l]*blk, r); i++) {
        if (a[i] + lazy[b[l]] < val)
            ret = max(ret, a[i] + lazy[b[l]]);
    }
    if (b[l] != b[r]) {
        for (int i = (b[r] - 1) * blk + 1; i <= r; i++) {
            if (a[i] + lazy[b[r]] < val)
                ret = max(ret, a[i] + lazy[b[r]]);
        }
    }
    for (int i = b[l] + 1; i <= b[r] - 1; i++) {
        ll get = val - lazy[i];
        vector<ll>::iterator l = lower_bound(vet[i].begin(), vet[i].end(), get);
        if (l == vet[i].begin())
            continue;
        l --;
        ret = max(ret, *l + lazy[i]);
    }
    return ret;
}
int main() {
    n = read;
    for (int i = 1; i <= n; i++)
        a[i] = read;
    blk = sqrt(n);
    for (int i = 1; i <= n; i++) {
        b[i] = (i - 1) / blk + 1;
        vet[b[i]].push_back(a[i]);
    }
    for (int i = 1; i <= b[n]; i++)
        sort(vet[i].begin(), vet[i].end());
    for (int i = 1; i <= n; i++) {
        int op = read, l = read, r = read, c = read;
        if (op == 0)
            update(l, r, c);
        else
            printf("%lld\n", query(l, r, c));
        //      debug(i);
    }
    return 0;
}
/**
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4
3
-1
**/


入门 4-区间加法-区间查询


61c58380409f49ae95f89b3068249050.png


ll n,a[maxn];
ll blk,lazy[maxn],b[maxn],sum[maxn];
void update(ll l,ll r,ll c) {
  for(int i=l; i<=min(b[l]*blk,r); i++) a[i] += c,sum[b[l]] += c;
  if(b[l] != b[r]) {
    for(int i=(b[r] - 1) * blk+1; i<=r; i++) a[i] += c,sum[b[r]] += c;
  }
  for(int i=b[l]+1; i<=b[r] - 1; i++) {
    lazy[i] += c;
  }
}
ll query(ll l,ll r,ll val) {
  ll ret = 0;
  for(int i=l; i<=min(b[l]*blk,r); i++) {
    ret += a[i] + lazy[b[l]];
    ret %= (val + 1);
  }
  if(b[l] != b[r]) {
    for(int i=(b[r]-1)*blk+1; i<=r; i++) {
      ret += a[i] + lazy[b[r]];
      ret %= (val + 1);
    }
  }
  for(int i=b[l]+1; i<=b[r]-1; i++) {
    ll add = lazy[i] * blk % (val + 1);
    ret += (sum[i] + add) % (val + 1);
    ret %= (val + 1);
  }
  return ret;
}
int main() {
  n = read;
  for(int i=1; i<=n; i++) a[i] = read;
  blk = sqrt(n);
  for(int i=1; i<=n; i++) {
    b[i] = (i - 1) / blk + 1;
    sum[b[i]] += a[i];
  }
  for(int i=1; i<=n; i++) {
    int op = read,l = read,r = read,c = read;
    if(op == 0) update(l,r,c);
    else printf("%lld\n",query(l,r,c));
  }
  return 0;
}
/**
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4
1
4
**/


入门 5-区间开方-区间查询


41aa87339eab4d2382670622f191bd65.png


ll n,a[maxn];
ll blk,lazy[maxn],b[maxn],sum[maxn];
bool vis[maxn];
bool check(int id) {
  if(vis[id]) return true;
  for(int i=(id-1)*blk+1; i<=min(n,blk*id); i++) {
    if(a[i] > 1) return false;
  }
  return vis[id] = 1;
}
void update(ll l,ll r) {
  if(!check(b[l])) {
    for(int i=l; i<=min(b[l]*blk,r); i++) {
      sum[b[l]] -= a[i];
      a[i] = sqrt(a[i]);
      sum[b[l]] += a[i];
    }
  }
  if(b[l] != b[r] && !check(b[r])) {
    for(int i=(b[r]-1)*blk+1; i<=r; i++) {
      sum[b[r]] -= a[i];
      a[i] = sqrt(a[i]);
      sum[b[r]] += a[i];
    }
  }
  for(int i=b[l]+1; i<=b[r]-1; i++) {
    if(!check(i)) {
      sum[i] = 0;
      for(int j=(i-1)*blk+1; j<=i*blk; j++) {
        a[j] = sqrt(a[j]);
        sum[i] += a[j];
      }
    }
  }
}
ll query(ll l,ll r) {
  ll ret = 0;
  for(int i=l; i<=min(b[l]*blk,r); i++) {
    ret += a[i];
  }
  if(b[l] != b[r]) {
    for(int i=(b[r]-1)*blk+1; i<=r; i++) {
      ret += a[i];
    }
  }
  for(int i=b[l]+1; i<=b[r]-1; i++) {
    ret += sum[i];
  }
  return ret;
}
int main() {
  n = read;
  for(int i=1; i<=n; i++) a[i] = read;
  blk = sqrt(n);
  for(int i=1; i<=n; i++) {
    b[i] = (i - 1) / blk + 1;
    sum[b[i]] += a[i];
  }
  for(int i=1; i<=n; i++) {
    int op = read,l = read,r = read,c = read;
    if(op == 0) update(l,r);
    else printf("%lld\n",query(l,r));
  }
  return 0;
}
/**
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4
6
2
**/


目录
相关文章
|
算法 容器
算法:双指针解决数组划分和数组分块问题
算法:双指针解决数组划分和数组分块问题
|
6月前
|
存储 算法 vr&ar
☆打卡算法☆LeetCode 209. 长度最小的子数组 算法解析
☆打卡算法☆LeetCode 209. 长度最小的子数组 算法解析
|
6月前
|
存储 机器学习/深度学习 人工智能
【408数据结构与算法】—数组和特殊矩阵的压缩存储(二十五)
【408数据结构与算法】—数组和特殊矩阵的压缩存储(二十五)
|
算法
7-2 整除分块
7-2 整除分块
83 0
|
人工智能 vr&ar
数列分块入门 1 (单点查值,区间加法)
数列分块入门 1 (单点查值,区间加法)
78 0
|
存储 5G 容器
一个很大的文件,存放了10G个整数的乱序数列,如何用程序找出中位数。
一个很大的文件,存放了10G个整数的乱序数列,如何用程序找出中位数。
100 0
|
搜索推荐 C语言
用c语言代码将数列8、6、1、9、2从大到小排序。(要求:画出冒泡排序算法的排序过程)
用c语言代码将数列8、6、1、9、2从大到小排序。(要求:画出冒泡排序算法的排序过程)
116 0
|
人工智能
LOJ—— 数列分块入门 2
LOJ—— 数列分块入门 2
86 0
|
人工智能 vr&ar
LOJ——数列分块入门1
LOJ——数列分块入门1
92 0
|
机器学习/深度学习 存储 人工智能
LOJ6285.数列分块入门 9(分块在线求区间众数)
LOJ6285.数列分块入门 9(分块在线求区间众数)
136 0