zoukankan      html  css  js  c++  java
  • 莫队/分块 题目泛做

    题目1 BZOJ2453 / 2120

    算法讨论:

    用pre[i]表示与第i个位置颜色相同的上个位置在哪里,那么对于l...r内,如果一个位置的pre[i] < l,则说明这个颜色是第一次出现。

    然后暴力分块。因为修改的次数很少,所以每次修改就重新计算pre[i],对于涉及的块重新构块。然后对于整块的查询,直接在排好序的pre上二分就可以了。

      1 #include <bits/stdc++.h>
      2  
      3 using namespace std;
      4  
      5 const int M = 1000000 + 5;
      6 const int N = 10000 + 5;
      7 const int K = 110;
      8  
      9 inline int read() {
     10   int x = 0;
     11   char c = getchar();
     12  
     13   while(!isdigit(c)) c = getchar();
     14   while(isdigit(c)) {
     15     x = x * 10 + c - '0';
     16     c = getchar();
     17   }
     18   return x;
     19 }
     20  
     21 char ss[5];
     22 int n, m, size, tk;
     23 int ckn[N], b[N], pre[N], last[M], a[N];
     24 int l[K], r[K];
     25  
     26 void prepare() {
     27   size = (int) sqrt(n);
     28   for(int i = 1; i <= n; ++ i) ckn[i] = (i - 1) / size + 1;
     29   tk = n / size + 1 - (n % size == 0);
     30   for(int i = 1; i <= tk; ++ i) {
     31     l[i] = (i - 1) * size + 1;
     32     r[i] = min(i * size, n);
     33     for(int j = l[i]; j <= r[i]; ++ j) {
     34       b[j] = pre[j];
     35     }
     36     sort(b + l[i], b + r[i] + 1);
     37   }
     38 }
     39  
     40 void reset(int num) {
     41   for(int i = l[num]; i <= r[num]; ++ i) {
     42     b[i] = pre[i];
     43   }
     44   sort(b + l[num], b + r[num] + 1);
     45 }
     46  
     47 void update(int x, int v) {
     48   int tp;
     49    
     50   for(int i = 1; i <= n; ++ i) last[a[i]] = 0;
     51   a[x] = v;
     52   for(int i = 1; i <= n; ++ i) {
     53     tp = pre[i];
     54     pre[i] = last[a[i]];
     55     if(tp != pre[i]) reset(ckn[i]);
     56     last[a[i]] = i;
     57   }
     58 }
     59  
     60 int bs(int L, int R, int V) {
     61   int mid, res, Down = L;
     62  
     63   if(b[R] < V) return R - L + 1;
     64   if(b[L] >= V) return 0;
     65   while(L <= R) {
     66     mid = L + (R - L) / 2;
     67     if(b[mid] < V) {
     68       L = mid + 1;
     69       res = mid;
     70     }
     71     else
     72       R = mid - 1;
     73   }
     74   return res - Down + 1;
     75 }
     76  
     77 void query(int L, int R) {
     78   int n1 = ckn[L], n2 = ckn[R];
     79   int res = 0;
     80    
     81   if(n1 == n2) {
     82     for(int i = L; i <= R; ++ i) {
     83       if(pre[i] < L) ++ res;
     84     }
     85     printf("%d
    ", res);
     86   }
     87   else {
     88     for(int i = L; i <= r[n1]; ++ i)
     89       if(pre[i] < L) ++ res;
     90     for(int i = l[n2]; i <= R; ++ i)
     91       if(pre[i] < L) ++ res;
     92     for(int i = n1 + 1; i < n2; ++ i)
     93       res += bs(l[i], r[i], L);
     94     printf("%d
    ", res);
     95   }
     96 }
     97  
     98 int main() {
     99   int x, y;
    100    
    101   n = read(); m = read();
    102   for(int i = 1; i <= n; ++ i) a[i] = read();
    103   for(int i = 1; i <= n; ++ i) {
    104     pre[i] = last[a[i]];
    105     last[a[i]] = i;
    106   }
    107   prepare();
    108   for(int i = 1; i <= m; ++ i) {
    109     scanf("%s", ss);
    110     x = read(); y = read();
    111     if(ss[0] == 'Q') {
    112       query(x, y);
    113     }
    114     else {
    115       update(x, y);
    116     }
    117   }
    118   return 0;
    119 }
    BZOJ2120

    题目2 BZOJ3052 WC2013 糖果公园

    算法讨论:

    带修改的树上莫队。

      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #include <cctype>
      7 #include <cmath>
      8 #include <stack>
      9 
     10 using namespace std;
     11 
     12 const int N = 100000 + 5;
     13 typedef long long ll;
     14 
     15 inline int read() {
     16   int x = 0;
     17   char c = getchar();
     18 
     19   while(!isdigit(c)) c = getchar();
     20   while(isdigit(c)) {
     21     x = x * 10 + c - '0';
     22     c = getchar();
     23   }
     24   return x;
     25 }
     26 
     27 int buf[30];
     28 
     29 inline void output(ll x) {
     30   int p = 0;
     31 
     32   buf[0] = 0;
     33   if(x == 0) p ++;
     34   else {
     35     while(x) {
     36       buf[p ++] = x % 10;
     37       x /= 10;
     38     }
     39   }
     40   for(int j = p - 1; j >= 0; -- j)
     41     putchar('0' + buf[j]);
     42 }
     43 
     44 ll ans[N], tot = 0;
     45 int n, m, q, size, cnt, tk, tim;
     46 int head[N], fa[N], f[N][18], seq[N], v[N], w[N];
     47 int ckn[N], depth[N], son[N], pre[N], c[N];
     48 bool flag[N]; int vis[N];
     49 stack <int> s;
     50 
     51 struct Edge {
     52   int from, to, next;
     53 }edges[N << 1];
     54 struct Query {
     55   int x, v, pre;
     56 }C[N];
     57 struct query {
     58   int id, u, v, t;
     59   bool operator < (const query &k) const {
     60     if(ckn[u] == ckn[k.u] && ckn[v] == ckn[k.v]) return t < k.t;
     61     else if(ckn[u] == ckn[k.u]) return ckn[v] < ckn[k.v];
     62     else return ckn[u] < ckn[k.u];
     63   }
     64 }Q[N];
     65 
     66 void insert(int from, int to) {
     67   ++ cnt;
     68   edges[cnt].from = from; edges[cnt].to = to;
     69   edges[cnt].next = head[from]; head[from] = cnt;
     70 }
     71 
     72 void dfs(int u, int f) {
     73   fa[u] = f; seq[u] = ++ tim;
     74   for(int i = head[u]; i; i = edges[i].next) {
     75     int v = edges[i].to;
     76 
     77     if(v != f) {
     78       depth[v] = depth[u] + 1;
     79       dfs(v, u);
     80       son[u] += son[v];
     81       if(son[u] >= size) {
     82         ++ tk;
     83         son[u] = 0;
     84         while(!s.empty()) {
     85           int cur = s.top(); s.pop();
     86           ckn[cur] = tk;
     87         }
     88       }
     89     }
     90   }
     91   s.push(u); son[u] ++;
     92 }
     93 
     94 void prepare() {
     95   memset(f, -1, sizeof f);
     96   for(int i = 1; i <= n; ++ i) f[i][0] = fa[i];
     97   for(int j = 1; (1 << j) <= n; ++ j) {
     98     for(int i = 1; i <= n; ++ i) {
     99       if(f[i][j - 1] != -1) {
    100         f[i][j] = f[f[i][j - 1]][j - 1];
    101       }
    102     }
    103   }
    104 }
    105 
    106 int lca(int a, int b) {
    107   int i;
    108 
    109   if(depth[a] < depth[b]) swap(a, b);
    110   for(i = 0; (1 << i) <= depth[a]; ++ i);
    111   -- i;
    112   for(int j = i; j >= 0; -- j) {
    113     if(depth[a] - depth[b] >= (1 << j))
    114       a = f[a][j];
    115   }
    116   if(a == b) return a;
    117   for(int j = i; j >= 0; -- j) {
    118     if(f[a][j] != -1 && f[a][j] != f[b][j]) {
    119       a = f[a][j];
    120       b = f[b][j];
    121     }
    122   }
    123   return f[a][0];
    124 }
    125 
    126 void rever(int u) {
    127   if(flag[u]) {
    128     flag[u] = false;
    129     tot -= 1LL * w[vis[c[u]]] * v[c[u]];
    130     vis[c[u]] --;
    131   }
    132   else {
    133     flag[u] = true;
    134     vis[c[u]] ++;
    135     tot += 1LL * w[vis[c[u]]] * v[c[u]];
    136   }
    137 }
    138 
    139 void Getpath(int u, int fi) {
    140   while(u != fi) {
    141     rever(u);
    142     u = fa[u];
    143   }
    144 }
    145 
    146 void change(int x, int v) {
    147   if(flag[x]) {
    148     rever(x); c[x] = v; rever(x);
    149   }
    150   else c[x] = v;
    151 }
    152 
    153 void solve(int nl, int nr, int &zl, int &zr, int ts) {
    154   int Lca;
    155 
    156   Lca = lca(nl, zl);
    157   Getpath(nl, Lca); Getpath(zl, Lca);
    158   Lca = lca(nr, zr);
    159   Getpath(nr, Lca); Getpath(zr, Lca);
    160   Lca = lca(nl, nr);
    161   rever(Lca); ans[Q[ts].id] = tot; rever(Lca);
    162   zl = nl; zr = nr;
    163 }
    164 
    165 #define ONLINE_JUDGE
    166 
    167 int main() {
    168   //int __size__ =  64 <<20;  //这里谁<<20位,就是多少M的栈
    169   //char*__p__ =(char*)malloc(__size__)+ __size__;
    170   //__asm__("movl %0, %%esp
    "::"r"(__p__));
    171 
    172 #ifndef ONLINE_JUDGE
    173   freopen("park.in", "r", stdin);
    174   freopen("park.out", "w", stdout);
    175 #endif
    176 
    177   int x, y;
    178 
    179   n = read(); m = read(); q = read();
    180   for(int i = 1; i <= m; ++ i) v[i] = read();
    181   for(int i = 1; i <= n; ++ i) w[i] = read();
    182   for(int i = 1; i < n; ++ i) {
    183     x = read(); y = read();
    184     insert(x, y); insert(y, x);
    185   }
    186   for(int i = 1; i <= n; ++ i) pre[i] = c[i] = read();
    187   depth[1] = 1; //size = (int) pow((double) n, (double) 2 / 3);
    188   size = 1500;
    189   dfs(1, -1);
    190   if(!s.empty()) {
    191     ++ tk;
    192     while(!s.empty()) {
    193       int cur = s.top(); s.pop();
    194       ckn[cur] = tk;
    195     }
    196   }
    197   prepare();
    198 
    199   int type, t1 = 0, t2 = 0;
    200   
    201   for(int i = 1; i <= q; ++ i) {
    202     type = read();
    203     if(!type) {
    204       ++ t1;
    205       C[t1].x = read(); C[t1].v = read(); C[t1].pre = pre[C[t1].x];
    206       pre[C[t1].x] = C[t1].v;
    207     }
    208     else {
    209       ++ t2;
    210       Q[t2].u = read(); Q[t2].v = read(); Q[t2].id = t2; Q[t2].t = t1;
    211       if(seq[Q[t2].u] > seq[Q[t2].v]) swap(Q[t2].u, Q[t2].v);
    212     }
    213   }
    214 
    215   int L = 1, R = 1;
    216 
    217   sort(Q + 1, Q + t2 + 1);
    218   for(int i = 1; i <= Q[1].t; ++ i) {
    219     change(C[i].x, C[i].v);
    220   }
    221   solve(Q[1].u, Q[1].v, L, R, 1);
    222   for(int i = 2; i <= t2; ++ i) {
    223     for(int t = Q[i - 1].t + 1; t <= Q[i].t; ++ t)
    224       change(C[t].x, C[t].v);
    225     for(int t = Q[i - 1].t; t > Q[i].t; -- t)
    226       change(C[t].x, C[t].pre);
    227     solve(Q[i].u, Q[i].v, L, R, i);
    228   }
    229   for(int i = 1; i <= t2; ++ i) {
    230     output(ans[i]);
    231     puts("");
    232   }
    233   
    234 #ifndef ONLINE_JUDGE
    235   fclose(stdin); fclose(stdout);
    236 #endif
    237   return 0;
    238 }
    BZOJ 3052

    题目3 NOI2003 文本编辑器

    算法讨论:

    块状链表。支持插入、删除、找到第x个数的位置等操作。

    对于插入操作,

    如果要插入的当前块的大小已经满块
    那么就新建立一个块,插到原来的两块之间,修改块之间的指针
    然后把这个新块之前的块的光标之后的东西复制到新块,然后更新原块的size
    然后比较这两个块的大小,把字符插入到较小的那个块中去。

    对于删除操作

    首先判断当前块的光标之后的元素个数是否比删除的东西多,如果多的话,就直接在块内删除
    如果不是,则直接把块改了。

      1 #include <cstdlib>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <cstdio>
      6  
      7 using namespace std;
      8  
      9 const int K = 3000 + 5;
     10  
     11 char opt[10];
     12 int m;
     13 int cur_mouse, cur_blo, tk, size;
     14 //cur_mouse 记录光标在某个块内的位置
     15 //cur_blo记录当前在某个块 tk是块的总数  size是块的上限大小
     16 struct Node {
     17   char s[K];
     18   int sz, pre, next;
     19 }blo[K];
     20  
     21 void Move() {
     22   int mouse;
     23   scanf("%d", &mouse);
     24   cur_blo = blo[0].next;
     25   while(mouse > blo[cur_blo].sz) {
     26     mouse -= blo[cur_blo].sz; cur_blo = blo[cur_blo].next;
     27   }
     28   cur_mouse = mouse;
     29 }
     30  
     31 void Insert() {
     32   int cmd, imouse = cur_mouse, iblo = cur_blo;
     33   char c;
     34   scanf("%d", &cmd);
     35   c = getchar();
     36   while(cmd --) {
     37     while(c < 32 || c > 126) c = getchar();
     38     if(blo[iblo].sz == size) {
     39       ++ tk;
     40       blo[tk].next = blo[iblo].next;
     41       blo[tk].pre = iblo; blo[tk].sz = size - imouse;
     42       blo[blo[iblo].next].pre = tk;
     43       blo[iblo].next = tk;
     44       for(int i = 1; i <= blo[tk].sz; ++ i)
     45         blo[tk].s[i] = blo[iblo].s[imouse + i];
     46       blo[iblo].sz = imouse;
     47       if(blo[tk].sz < blo[iblo].sz) {
     48         imouse = 0; iblo = tk;
     49       }
     50     }
     51     blo[iblo].sz ++;
     52     for(int i = blo[iblo].sz; i > imouse; -- i) {
     53       blo[iblo].s[i] = blo[iblo].s[i - 1];
     54     }
     55     blo[iblo].s[++ imouse] = c;
     56     c = getchar();
     57   }
     58 }
     59  
     60 void Delete() {
     61   int cmd, imouse = cur_mouse, iblo = cur_blo;
     62   scanf("%d", &cmd);
     63   while(cmd) {
     64     int left = blo[iblo].sz - imouse;
     65     if(cmd > left) {
     66       cmd -= left; blo[iblo].sz = imouse;
     67       iblo = blo[iblo].next;
     68       imouse = 0;
     69     }
     70     else {
     71       for(int i = imouse + cmd + 1; i <= blo[iblo].sz; ++ i)
     72         blo[iblo].s[i - cmd] = blo[iblo].s[i];
     73       blo[iblo].sz -= cmd;
     74       cmd = 0;
     75     }
     76   }
     77 }
     78  
     79 void Next() {
     80   if(cur_mouse != blo[cur_blo].sz) cur_mouse ++;
     81   else {
     82     cur_blo = blo[cur_blo].next;
     83     while(blo[cur_blo].sz == 0) {
     84       blo[blo[cur_blo].pre].next = blo[cur_blo].next;
     85       blo[blo[cur_blo].next].pre = blo[cur_blo].pre;
     86       cur_blo = blo[cur_blo].next;
     87     }
     88     cur_mouse = 1;
     89   }
     90 }
     91  
     92 void Prev() {
     93   if(cur_mouse) cur_mouse --;
     94   else {
     95     cur_blo = blo[cur_blo].pre;
     96     while(blo[cur_blo].sz == 0) {
     97       blo[blo[cur_blo].pre].next = blo[cur_blo].next;
     98       blo[blo[cur_blo].next].pre = blo[cur_blo].pre;
     99       cur_blo = blo[cur_blo].pre;
    100     }
    101     cur_mouse = blo[cur_blo].sz - 1;
    102   }
    103 }
    104  
    105 void Get() {
    106   int cmd, imouse = cur_mouse, iblo = cur_blo;
    107   scanf("%d", &cmd);
    108   while(cmd) {
    109     if(blo[iblo].sz == 0) {
    110       blo[blo[iblo].next].pre = blo[iblo].pre;
    111       blo[blo[iblo].pre].next = blo[iblo].next;
    112       iblo = blo[iblo].next;
    113     }
    114     int left = blo[iblo].sz - imouse;
    115     if(cmd > left) {
    116       for(int i = imouse + 1; i <= blo[iblo].sz; ++ i)
    117         putchar(blo[iblo].s[i]);
    118       cmd -= left;
    119       imouse = 0;
    120       iblo = blo[iblo].next;
    121     }
    122     else {
    123       for(int i = imouse + 1; i <= imouse + cmd; ++ i)
    124         putchar(blo[iblo].s[i]);
    125       cmd = 0;
    126     }
    127   }
    128   puts("");
    129 }
    130  
    131 #define ONLINE_JUDGE
    132  
    133 int main() {
    134 #ifndef ONLINE_JUDGE
    135   freopen("editor2003.in", "r", stdin);
    136   freopen("editor2003.out", "w", stdout);
    137 #endif
    138  
    139   scanf("%d", &m);
    140   size = 2000;
    141   tk = 1; cur_blo = 1;
    142   blo[0].next = 1;//忘记链表初始化。。额。
    143   while(m --) {
    144     scanf("%s", opt);
    145     if(opt[0] == 'M') Move();
    146     else if(opt[0] == 'I') Insert();
    147     else if(opt[0] == 'D') Delete();
    148     else if(opt[0] == 'G') Get();
    149     else if(opt[0] == 'P') Prev();
    150     else if(opt[0] == 'N') Next();
    151   }
    152  
    153 #ifndef ONLINE_JUDGE
    154   fclose(stdin); fclose(stdout);
    155 #endif
    156  
    157   return 0;
    158 }
    NOI 2003
  • 相关阅读:
    https://developer.aliyun.com/ebook?utm_content=g_1000256420
    形容词在句子中的位置
    顺风水水
    https://www.youtube.com/watch?v=pVIywLXDuRo 有趣到流泪
    经济机器是怎样运行的 (时长30分钟) Ray Dalio
    https://codepen.io/deadzq-the-decoder/pen/qBqQYXg
    Vue 10 test
    vue day2
    codepen学Vue day2
    代理总结更新
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5282337.html
Copyright © 2011-2022 走看看