• [luoguP2801] 教主的魔法(二分 + 分块)


    传送门

    以为对于这类问题线段树都能解决,分块比线段树菜,结果培训完才知道线段树是一种特殊的分块方法,有的分块的题线段树不能做,看来分块还是有必要学的。

    对于这个题,先分块,然后另开一个数组对于每个块内排序。

    区间加的话,加一个标记,每一个整块区间加,里面的数的相对大小不变,而左右两边零散的块直接暴力重构。

    查询可以对于每个块二分查找。

    时间复杂度应该是 nlogn + Q√nlog√n,刚好卡过。。

    注意:第10个点会被卡,手写二分比stl的lower_bound快一点,可以避免被卡。

       也可以在 S = sqrt(n) 后面 + x,x 不要太大也不要太小,不知道为什么,速度也会快点,玄学啊。

    %%%有些dalao不知道怎么写的,1000ms

    ——代码(最终只能优化到1600ms)

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <iostream>
      4 #include <algorithm>
      5 #define LL long long
      6 
      7 const int MAXN = 1000001;
      8 int n, q, S, C;
      9 int belong[MAXN], st[MAXN], ed[MAXN];
     10 LL a[MAXN], b[MAXN], add[MAXN];
     11 
     12 inline LL read()
     13 {
     14     LL x = 0, f = 1;
     15     char ch = getchar();
     16     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
     17     for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
     18     return x * f;
     19 }
     20 
     21 inline int find(int x, int y, int z)
     22 {
     23     int mid;
     24     while(x < y)
     25     {
     26         mid = (x + y) >> 1;
     27         if(b[mid] >= z) y = mid;
     28         else x = mid + 1;
     29     }
     30     return x;
     31 }
     32 
     33 inline void retreat(int x, int y)
     34 {
     35     int i;
     36     for(i = x; i <= y; i++) b[i] = a[i];
     37     std::sort(b + x, b + y + 1);
     38 }
     39 
     40 inline void init()
     41 {
     42     int i, j;
     43     S = int(sqrt(n)) + 10;
     44     for(i = 1; i <= n; i++) scanf("%d", &a[i]);
     45     for(i = 1; i <= n; i += S)
     46     {
     47         st[++C] = i;
     48         ed[C] = std::min(i + S - 1, n);
     49     }
     50     for(i = 1; i <= C; i++)
     51         for(j = st[i]; j <= ed[i]; j++)
     52             belong[j] = i;
     53     for(i = 1; i <= C; i++) retreat(st[i], ed[i]);
     54 }
     55 
     56 inline void update(int x, int y, LL z)
     57 {
     58     int i, l = belong[x], r = belong[y];
     59     if(l == r)
     60     {
     61         for(i = x; i <= y; i++) a[i] += z;
     62         retreat(st[l], ed[r]);
     63     }
     64     else
     65     {
     66         for(i = x; i <= ed[l]; i++) a[i] += z;
     67         for(i = l + 1; i <= r - 1; i++) add[i] += z;
     68         for(i = st[r]; i <= y; i++) a[i] += z;
     69         retreat(st[l], ed[l]);
     70         retreat(st[r], ed[r]);
     71     }
     72 }
     73 
     74 inline int query(int x, int y, LL z)
     75 {
     76     int i, l = belong[x], r = belong[y], ans = 0;
     77     if(l == r) return y + 1 - find(x, y + 1, z - add[l]);
     78     ans += ed[l] - find(x, ed[l] + 1, z - add[l]) + 1;
     79     for(i = l + 1; i <= r - 1; i++) ans += ed[i] - find(st[i], ed[i] + 1, z - add[i]) + 1;
     80     ans += y - find(st[r], y + 1, z - add[r]) + 1;
     81     return ans;
     82 }
     83 
     84 int main()
     85 {
     86     int i, j, x, y;
     87     LL z;
     88     char ch;
     89     n = read();
     90     q = read();
     91     init();
     92     for(i = 1; i <= q; i++)
     93     {
     94         while ((ch=getchar()) < 'A' || ch > 'Z');
     95         x = read();
     96         y = read();
     97         z = read();
     98         if(ch == 'M') update(x, y, z);
     99         else printf("%d
    ", query(x, y, z));
    100     }
    101     return 0;
    102 }
    View Code
  • 相关阅读:
    我的第一个python web开发框架(27)——定制ORM(三)
    我的第一个python web开发框架(26)——定制ORM(二)
    我的第一个python web开发框架(25)——定制ORM(一)
    我的第一个python web开发框架(24)——系统重构与ORM
    我的第一个python web开发框架(23)——代码版本控制管理与接口文档
    我的第一个python web开发框架(22)——一个安全小事故
    CentOS7安装详解
    自动化运维工具-mussh工具安装配置及简单使用讲解
    自动化运维工具-pdsh工具安装配置及简单使用讲解
    自动化运维工具-pssh工具安装配置及简单使用讲解
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6823527.html
Copyright © 2020-2023  润新知