noip模拟赛 数颜色

分析:高级数据结构学傻了.....一眼看上去觉得是莫队,发现带修改,于是分块,由于写的常数很大,只有70分.

      正解很简单,记录下颜色为c的每只兔子的位置,每次二分找这个区间有多少只这种颜色的兔子就可以了,交换操作就交换位置,颜色.可能会存不下,所以用vector.

70分分块:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n, m, a[600][50010], b[300010], block, l[600], r[600], pos[300010], cnt, vis[300010];
bool flag = true;

void update(int cur)
{
    int t = b[cur], t2 = b[cur + 1];
    swap(b[cur], b[cur + 1]);
    int p1 = pos[cur], p2 = pos[cur + 1];
    a[p1][t]--;
    a[p2][t]++;
    a[p1][t2]++;
    a[p2][t2]--;
}

int query(int ll, int rr, int c)
{
    int L = pos[ll], R = pos[rr], res = 0;
    if (L >= R - 1)
    {
        for (int i = ll; i <= rr; i++)
            if (b[i] == c)
                res++;
        return res;
    }
    for (int i = L + 1; i <= R - 1; i++)
        res += a[i][c];
    for (int i = ll; i <= r[L]; i++)
        if (b[i] == c)
            res++;
    for (int i = l[R]; i <= rr; i++)
        if (b[i] == c)
            res++;
    return res;
}

int main()
{
    scanf("%d%d", &n, &m);
    block = sqrt(n);
    for (int i = 1; i <= n; i++)
        pos[i] = (i - 1) / block + 1;
    cnt = (n - 1) / block + 1;
    for (int i = 1; i <= cnt; i++)
        l[i] = r[i - 1] + 1, r[i] = min(block * i, n);
    for (int i = 1; i <= n; i++)
    {
        int t;
        scanf("%d", &t);
        a[pos[i]][t]++;
        b[i] = t;
    }
        while (m--)
        {
            int op, l, r, c;
            scanf("%d", &op);
            if (op == 1)
            {
                scanf("%d%d%d", &l, &r, &c);
                printf("%d\n", query(l, r, c));
            }
            else
            {
                scanf("%d", &c);
                update(c);
            }
        }

    return 0;
}

正解:

#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 300010;

int n, m, a[maxn];
vector <int>b[maxn];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        b[a[i]].push_back(i);
    }
    for (int i = 1; i <= n; i++)
        sort(b[i].begin(), b[i].end());
    while (m--)
    {
        int op, l, r, c;
        scanf("%d", &op);
        if (op == 1)
        {
            scanf("%d%d%d", &l, &r, &c);
            printf("%d\n", (int)(upper_bound(b[c].begin(), b[c].end(), r) - lower_bound(b[c].begin(), b[c].end(), l)));
        }
        else
        {
            scanf("%d", &c);
            if (a[c] != a[c + 1])
            {
                (*lower_bound(b[a[c]].begin(), b[a[c]].end(), c))++;
                (*lower_bound(b[a[c + 1]].begin(), b[a[c + 1]].end(), c + 1))--;
                swap(a[c], a[c + 1]);
            }
        }
    }

    return 0;
}

 

posted @ 2017-11-05 23:35  zbtrs  阅读(284)  评论(0编辑  收藏  举报