「2016山东省队集训」 Play with array

来源:互联网 发布:淘宝开店店铺简介 编辑:程序博客网 时间:2024/06/05 20:30

Description

http://7xqmhv.com1.z0.glb.clouddn.com/16-5-31/31000317.jpg

Input

http://7xqmhv.com1.z0.glb.clouddn.com/16-5-31/1933740.jpg

Output

http://7xqmhv.com1.z0.glb.clouddn.com/16-5-31/652259.jpg

Sample Input

7
6 6 2 7 4 2 5
7
1 3 6
2 2 4 2
2 4 6 2
2 3 3 6
1 2 6
1 1 4
2 1 7 3

Sample Output

2
1
0
0

HINT

http://7xqmhv.com1.z0.glb.clouddn.com/16-5-31/53994786.jpg

Source

by faebdc

Solution

块状链表。

  • 修改操作可以转化为:删除r、在l前面插入一个数。
  • 询问操作可以转化为:区间[1,r]中k出现次数-区间[1,l-1]中k出现次数

对于每个块记录一下每个数字出现了多少次。

错误调试:split的操作要对每个块数字出现次数进行修改。

Code

#include <cstdio>#include <algorithm>using namespace std;const int size = 316;const int maxn = 100005;int getint() {    int r = 0, k = 1; char c = getchar();    for (; '0' > c || c > '9'; c = getchar()) if (c == '-') k = -1;    for (; '0' <= c && c <= '9'; c = getchar()) r = r * 10 - '0' + c;    return r * k;}int n, m, totBlock;int data[640][2005], cnt[640][100005], nxtBlock[640], preBlock[640], siz[640], a[maxn];void Build() {    totBlock = (n + size - 1) / size;    for (int i = 1; i <= totBlock; ++i) {        int l = (i - 1) * size + 1, r = min(i * size, n);        siz[i] = r - l + 1;        for (int j = l; j <= r; ++j) {            ++cnt[i][a[j]];            data[i][j - l + 1] = a[j];        }        nxtBlock[i] = i + 1;        preBlock[i] = i - 1;    }    nxtBlock[totBlock] = 0;}int Query(int pos) {    int tmp = 0;    for (int i = 1; i; i = nxtBlock[i]) {        tmp += siz[i];        if (pos <= tmp)            return data[i][pos - tmp + siz[i]];    }}void Merge(int x, int y) {    for (int i = 1; i <= siz[y]; ++i) {        data[x][++siz[x]] = data[y][i];        ++cnt[x][data[y][i]];    }    nxtBlock[x] = nxtBlock[y];}void Split(int x) {    ++totBlock; int half = siz[x] / 2;    for (int i = half + 1; i <= siz[x]; ++i) {        data[totBlock][++siz[totBlock]] = data[x][i];        --cnt[x][data[x][i]];        ++cnt[totBlock][data[x][i]];    }    siz[x] = half;    preBlock[totBlock] = x;    nxtBlock[totBlock] = nxtBlock[x];    if (nxtBlock[x])        preBlock[nxtBlock[x]] = totBlock;    nxtBlock[x] = totBlock;}void Delete(int pos) {    int tmp = 0;    for (int i = 1; i; i = nxtBlock[i]) {        tmp += siz[i];        if (pos <= tmp) {            tmp -= siz[i];            --cnt[i][data[i][pos - tmp]];            for (int j = pos - tmp; j <= siz[i]; ++j)                data[i][j] = data[i][j + 1];            --siz[i];            if (siz[i] * 2 < size) {                if (nxtBlock[i]) {                    Merge(i, nxtBlock[i]);                } else if (preBlock[i]) {                    Merge(preBlock[i], i);                    i = preBlock[i];                }            }            if (siz[i] > size * 2)                Split(i);            return;        }    }}void Insert(int pos, int val) {    int tmp = 0;    for (int i = 1; i; i = nxtBlock[i]) {        tmp += siz[i];        if (pos <= tmp) {            tmp -= siz[i]; ++cnt[i][val];            for (int j = siz[i]; j >= pos - tmp; --j)                data[i][j + 1] = data[i][j];            ++siz[i]; data[i][pos - tmp] = val;            if (siz[i] > size * 2)                Split(i);            return;        }    }}int Query(int pos, int k) {    int tmp = 0, ret = 0;    for (int i = 1; i; i = nxtBlock[i]) {        tmp += siz[i];        if (pos <= tmp) {            pos -= tmp - siz[i];            for (int j = 1; j <= pos; ++j)                ret += (data[i][j] == k);            return ret;        }        ret += cnt[i][k];    }    return ret;}int main() {    freopen("array.in", "r", stdin);    freopen("array.out", "w", stdout);    int x, l, r, k;    n = getint();    for (int i = 1; i <= n; ++i)        a[i] = getint();    Build();    m = getint();    for (int i = 1; i <= m; ++i) {        x = getint(); l = getint(); r = getint();        if (x == 1) {            int tmp = Query(r);            Delete(r);            Insert(l, tmp);        } else {            k = getint();            printf("%d\n", Query(r, k) - Query(l - 1, k));        }    }    fclose(stdin);    fclose(stdout);    return 0;}
0 0
原创粉丝点击