Luo Gu P1972 [SDOI2009] HH necklace foundation of Mo + card team regular / off-line segment tree

Luo Gu P1972 [SDOI2009] HH necklace

label

  • Mo foundation team
  • Card Chang
  • Segment tree offline

Foreword

  • My blog csdn and garden are synchronized, Welcome danzh- blog Park ~
  • This is the most naked of Mo team mess. However, data strengthened, Mo + team needs oxygen to live a regular card, the card often talk about in this article is simple, the main speaker segment tree

Concise meaning of the questions

  • To a sequence, you ask each interval [L, R] how many different figures have

Thinking

  • This is the most naked of Mo team mess. However, data strengthened, Mo + team needs oxygen to live a regular card, then card often written summary of related operations in it ~
  • Then there is a less violent method with weights segment tree maintenance. (Very clever duck)
    -------------------------------------------- ---------- division line ------------------------------------- pigeon -----------------
  • First, we look at a group of samples:

\[1,2,4,5,2,4,2\]

  • We put the same number in the final set to 1

\[1,2,4,5,2,4,2\]

\[1,0,0,1,0,1,1\]

  • Because each only produce a number 1, so now required interval [L, R] of the number of different numbers, directly count the number 1 on the line.
  • Think about it, directly above statistics the number 1 is wrong. For example, the query [3,3], apparently found by the above method is 0, but actually it is 1. why? In fact, the above statistics are right, but only when the right end of the query is the last number, that is, the right end point r = 7, the right thing to (think about why), while the left end point can be any of.
  • Obviously when the right time is a fixed point, something that is above tree line can be used to maintain, maintenance intervals and look on it.
  • Always ask the right point but not the same. How to do it? Chairman of thinking can make use of the tree, every move once the right point, you update about the current tree line, tree line maintenance to ensure that the current interval and r.
  • So should be offline, to ask the right point in accordance with sorting, each right end point increase on the first update about the tree line, then the query.
  • Finally talk about the updated tree line, such as to be updated i = 5. So 01 sequence should be of 5 to 1, then put in front of a number of 2 to 52, the segment tree will he 0. So we need to pre-treatment number per a [i] is his previous and the same number in the table, so this problem can be AC

Precautions

  • no

to sum up

Mo Team section

  • Fast read and write speed
inline int read()
{
    int ans = 0;
    char r = getchar(); bool neg = false;
    while (r<'0' || r>'9') { if (r == '-')neg = true; r = getchar(); }
    while (r >= '0'&&r <= '9') { ans = ans * 10 + r - '0'; r = getchar(); }
    return (neg) ? -ans : ans;
}
void write(int x) {
    if (x < 0) { putchar('-'); x = -x; }
    if (x > 9)write(x / 10);
    putchar(x % 10 + '0');
}//write不带换行符,需要自己putchar('\n')
  • Sort parity
bool operator < (const Query& a)const
{
    return pos[l] ^ pos[a.l] ? pos[l] < pos[a.l] : pos[l] & 1 ? r<a.r : r>a.r;
}
  • Size of block
int len =  n / sqrt(n * 2 / 3);

Segment tree section

  • This method should always be able to think of tree line off-line ~

AC Code

Mo team

#pragma GCC optimize(2)
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

inline int read()
{
    int ans = 0;
    char r = getchar(); bool neg = false;
    while (r<'0' || r>'9') { if (r == '-')neg = true; r = getchar(); }
    while (r >= '0'&&r <= '9') { ans = ans * 10 + r - '0'; r = getchar(); }
    return (neg) ? -ans : ans;
}
void write(int x) {
    if (x < 0) { putchar('-'); x = -x; }
    if (x > 9)write(x / 10);
    putchar(x % 10 + '0');
}

const int maxn = 1e6 + 10;

int pos[maxn];
struct Query
{
    int l, r, id;
    bool operator < (const Query& a)const
    {
        return pos[l] ^ pos[a.l] ? pos[l] < pos[a.l] : pos[l] & 1 ? r<a.r : r>a.r;
    }
};
Query query[maxn];

int n, q, a[maxn];

int ans, cnt[maxn];

int ans0[maxn];
void solve()
{
    scanf("%d", &n);
    int len =  n / sqrt(n * 2 / 3);
    for (int i = 1; i <= n; i++)
        a[i] = read(), pos[i] = (i - 1) / len + 1;
    scanf("%d", &q);
    for (int i = 1; i <= q; i++)
        query[i].l = read(), query[i].r = read(), query[i].id = i;
    sort(query + 1, query + 1 + q);

    int l = 1, r = 0;
    for (int i = 1; i <= q; i++)
    {
        int L = query[i].l, R = query[i].r;
        while (l < L) if (cnt[a[l++]]-- == 1) ans--;
        while (l > L)if (cnt[a[--l]]++ == 0) ans++;
        while (r < R) if (cnt[a[++r]]++ == 0) ans++;
        while (r > R) if (cnt[a[r--]]-- == 1) ans--;

        ans0[query[i].id] = ans;
    }

    for (int i = 1; i <= q; i++)
        write(ans0[i]), putchar('\n');
}

int main()
{
    //freopen("Testin.txt", "r", stdin);
    solve();
    return 0;
}

Segment tree

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 1e6 + 10;

struct Query
{
    int l, r, id;
    bool operator < (const Query& a)const
    {
        return r < a.r;
    }
};Query query[maxn];

struct Node
{
    int l, r, sum;
}; Node tree[maxn * 4];

void build(int o, int l, int r)
{
    tree[o].l = l, tree[o].r = r;
    if (l == r)
        return;
    int mid = (l + r) / 2;
    build(o * 2, l, mid);
    build(o * 2 + 1, mid + 1, r);
}

void change(int o, int x, int type)
{
    if (tree[o].l == tree[o].r)
    {
        tree[o].sum = type;
        return;
    }
    
    int mid = (tree[o].l + tree[o].r) / 2;
    if (x <= mid)
        change(o * 2, x, type);
    else
        change(o * 2 + 1, x, type);

    tree[o].sum = tree[o * 2].sum + tree[o * 2 + 1].sum;
}

int ask(int o, int l, int r)
{
    if (tree[o].l == l && tree[o].r == r)
        return tree[o].sum;

    int mid = (tree[o].l + tree[o].r) / 2;
    if (r <= mid)
        return ask(o * 2, l, r);
    else if (l > mid)
        return ask(o * 2 + 1, l, r);
    return ask(o * 2, l, mid) + ask(o * 2 + 1, mid + 1, r);
}

int n, q, a[maxn];

int ans0[maxn];
int las[maxn], pos[maxn];
void solve()
{
    build(1, 1, maxn - 10);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]), las[i] = pos[a[i]], pos[a[i]] = i;
    scanf("%d", &q);
    for (int i = 1; i <= q; i++)
        scanf("%d%d", &query[i].l, &query[i].r), query[i].id = i;
    sort(query + 1, query + 1 + q);

    int las_r = 1;
    for (int i = 1; i <= q; i++)
    {
        int l = query[i].l, r = query[i].r;
        for (int i = las_r; i <= r; i++)
        {
            if (las[i] != 0)
                change(1, las[i], 0);
            change(1, i, 1);
        }
            
        ans0[query[i].id] = ask(1, l, r);
        las_r = r + 1;
    }

    for (int i = 1; i <= q; i++)
        printf("%d\n", ans0[i]);
}

int main()
{
    freopen("Testin.txt", "r", stdin);
    solve();
    return 0;
}

Guess you like

Origin www.cnblogs.com/danzh/p/11323029.html