luogu P2801 教主的魔法

嘟嘟嘟

 

分块好题。

想法其实特别暴力,对于每一个块,都在块内排一个序,这样查询整块的时候二分找大于等于k - add[i]的数有多少。然后块外零散的数就暴力判断好啦。

所以有两个数组b[i][……]:代表第 i 块有哪些数;add[i]是整块加标记。

然后修改的时候,对于零散的数所在块,暴力重构b数组。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 using namespace std;
 12 #define enter puts("") 
 13 #define space putchar(' ')
 14 #define Mem(a, x) memset(a, x, sizeof(a))
 15 #define rg register
 16 typedef long long ll;
 17 typedef double db;
 18 const int INF = 0x3f3f3f3f;
 19 const db eps = 1e-8;
 20 const int maxn = 1e6 + 5;
 21 const int maxb = 1e3 + 5;
 22 inline ll read()
 23 {
 24   ll ans = 0;
 25   char ch = getchar(), last = ' ';
 26   while(!isdigit(ch)) {last = ch; ch = getchar();}
 27   while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
 28   if(last == '-') ans = -ans;
 29   return ans;
 30 }
 31 inline void write(ll x)
 32 {
 33   if(x < 0) x = -x, putchar('-');
 34   if(x >= 10) write(x / 10);
 35   putchar(x % 10 + '0');
 36 }
 37 
 38 int n, q, a[maxn];
 39 char c[2];
 40 
 41 int S, Cnt = 0, blo[maxn], lb[maxn], rb[maxn];
 42 int b[maxb][maxb], add[maxb];
 43 void init()
 44 {
 45   S = sqrt(n);
 46   Cnt = n % S ? n / S : n / S + 1;
 47   for(int i = 1; i <= Cnt; ++i) lb[i] = (i - 1) * S, rb[i] = i * S - 1;
 48   rb[Cnt] = n;
 49   for(int i = 1, j = 1; i <= n; ++i) blo[i] = j, j += (i == rb[j]);
 50   for(int i = 1, cb = 0; i <= Cnt; ++i, cb = 0)
 51     {
 52       for(int j = lb[i]; j <= rb[i]; ++j) b[i][++cb] = a[j];
 53       sort(b[i] + 1, b[i] + cb + 1);
 54     }
 55 }
 56 void update(int L, int R, int k)
 57 {
 58   int l = blo[L], r = blo[R], cb = 0;
 59   if(l == r)
 60     {
 61       for(int i = L; i <= R; ++i) a[i] += k;
 62       for(int i = lb[l]; i <= rb[l]; ++i) b[l][++cb] = a[i];
 63       sort(b[l] + 1, b[l] + cb + 1);
 64       return;
 65     }
 66   for(int i = l + 1; i < r; ++i) add[i] += k;
 67   for(int i = L; i <= rb[l]; ++i) a[i] += k;
 68   for(int i = lb[l]; i <= rb[l]; ++i) b[l][++cb] = a[i];
 69   sort(b[l] + 1, b[l] + cb + 1);
 70   cb = 0;
 71   for(int i = lb[r]; i <= R; ++i) a[i] += k;
 72   for(int i = lb[r]; i <= rb[r]; ++i) b[r][++cb] = a[i];
 73   sort(b[r] + 1, b[r] + cb + 1);
 74 }
 75 int query(int L, int R, int k)
 76 {
 77   int l = blo[L], r = blo[R], ret = 0;
 78   if(l == r)
 79     {
 80       for(int i = L; i <= R; ++i) ret += (a[i] + add[l] >= k);
 81       return ret;
 82     }
 83   for(int i = l + 1; i < r; ++i)
 84     {
 85       int tp = lower_bound(b[i] + 1, b[i] + rb[i] - lb[i] + 2, k - add[i]) - b[i];
 86       if(tp > rb[i] - lb[i] + 1) continue;
 87       ret += rb[i] - lb[i] + 1 - tp + 1;
 88     }
 89   for(int i = L; i <= rb[l]; ++i) ret += (a[i] + add[l] >= k);
 90   for(int i = lb[r]; i <= R; ++i) ret += (a[i] + add[l] >= k);
 91   return ret;
 92 }
 93 
 94 int main()
 95 {
 96   n = read(), q = read();
 97   for(int i = 1; i <= n; ++i) a[i] = read();
 98   init();
 99   for(int i = 1; i <= q; ++i)
100     {
101       scanf("%s", c);
102       int L = read(), R = read(), k = read();
103       if(c[0] == 'M') update(L, R, k);
104       else write(query(L, R, k)), enter;
105     }
106   return 0;
107 }
View Code

 

posted @ 2018-10-29 09:57  mrclr  阅读(160)  评论(0编辑  收藏  举报