P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链

题目背景

题目描述

HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此,他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。

输入输出格式

输入格式:

第一行:一个整数N,表示项链的长度。

第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间的整数)。

第三行:一个整数M,表示HH 询问的个数。

接下来M 行:每行两个整数,L 和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

输出格式:

M 行,每行一个整数,依次表示询问对应的答案。

输入输出样例

输入样例#1: 
6
1 2 3 4 3 5
3
1 2
3 5
2 6
输出样例#1: 
2
2
4

说明

数据范围:

对于100%的数据,N <= 500000,M <= 200000。

————————————————————————————————————————————————————————————

code

听说这是一道莫队入门题,虽然看着数据范围毒瘤,但还是尝试用莫队A掉此题

#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

const int MAXX = 1000010;
int n, m, a[MAXX], cnt[MAXX], ans[MAXX], sum;

struct Question {
    int l, r, id, pos;
    bool operator < (const Question &x) const {
        if (pos == x.pos) return r < x.r;
        return pos < x.pos;
    }
}q[MAXX];

inline int read() {
    int num = 0, f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {num = num * 10 + ch - '0'; ch = getchar();}
    return num * f;
}

void Add(int x) {sum += ++cnt[a[x]] == 1 ? 1 : 0;}
void Del(int x) {sum -= --cnt[a[x]] == 0 ? 1 : 0;}

int main() {
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
    n = read();
    for (int i = 1; i <= n; ++ i) a[i] = read();
    int Siz = ceil(sqrt(n));
    m = read();
    for (int i = 1; i <= m; ++ i) {
        q[i].l = read(); q[i].r = read();
        q[i].pos = q[i].l / Siz;
        q[i].id = i;
    }
    std::sort(q + 1, q + m + 1);
    int ql = q[1].l, qr = q[1].l - 1;
    for (int i = 1; i <= m; ++ i) {
        while (ql < q[i].l) Del(ql++);
        while (ql > q[i].l) Add(--ql);
        while (qr < q[i].r) Add(++qr);
        while (qr > q[i].r) Del(qr--);
        ans[q[i].id] = sum;
    } 
    for (int i = 1; i <= m; ++ i) printf("%d\n", ans[i]);
    return 0;
}

emmmmm……T掉了两个点

试图各种卡常,快速读入,快速输出,register,inline,++前缀,循环展开,呼吸新鲜空气等

// luogu-judger-enable-o2
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")

#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
#define put putchar('\n')

const int MAXX = 1000010;
int n, m, a[MAXX], cnt[MAXX], ans[MAXX], sum;

struct Question {
    int l, r, id, pos;
    bool operator < (const Question &x) const {
        if (pos == x.pos) return r < x.r;
        return pos < x.pos;
    }
}q[MAXX];

struct FastIO {
    static const int S = 1e7;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar() {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos++];
    }
    inline int xuint() {
        int c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x;
    }
    inline int xint() {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    inline void xstring(char *s) {
        int c = xchar();
        while (c <= 32) c = xchar();
        for (; c > 32; c = xchar()) * s++ = c;
        *s = 0;
    }
    inline void wchar(int x) {
        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
        wbuf[wpos++] = x;
    }
    inline void wint(long long x) {
        if (x < 0) wchar('-'), x = -x;
        char s[24];
        int n = 0;
        while (x || !n) s[n++] = '0' + x % 10, x /= 10;
        while (n--) wchar(s[n]);
        wchar('\n');
    }
    inline void wstring(const char *s) {
        while (*s) wchar(*s++);
    }
    ~FastIO() {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
} io;
inline void wr(int x){if (x<0) {putchar('-');wr(-x);return;}if(x>=10)wr(x/10);putchar(x%10+'0');}
inline void wrn(int x){wr(x);put;}

inline void Add(register int x) {sum += ++cnt[a[x]] == 1 ? 1 : 0;}
inline void Del(register int x) {sum -= --cnt[a[x]] == 0 ? 1 : 0;}

int main() {
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
    n = io.xint();
    for (register int i = 1; i <= n; ++ i) {
        a[i] = io.xint();
    }
    register int Siz = ceil(sqrt(n));
    m = io.xint();
    for (register int i = 1; i <= m; ++ i) {
        q[i].l = io.xint(), q[i].r = io.xint();
        q[i].pos = q[i].l / Siz;
        q[i].id = i;
    }
    std::sort(q + 1, q + m + 1);
    register int ql = q[1].l, qr = q[1].l - 1;
    for (register int i = 1; i <= m; ++ i) {
        while (ql < q[i].l) Del(ql++);
        while (ql > q[i].l) Add(--ql);
        while (qr < q[i].r) Add(++qr);
        while (qr > q[i].r) Del(qr--);
        ans[q[i].id] = sum;
    } 
    for (register int i = 1; i <= m; ++ i) {
        wrn(ans[i]);
    }
    return 0;
}

卡常失败*N

QWQ

看题解用大佬的神奇主席树终结此题

#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <map>
#include <queue>
#include <vector>

typedef long long LL;

const int MAXX = 10000010;
int n, m;
int cnt, lst[MAXX], tp[MAXX], rot[MAXX];

struct PTree {
    int l, r, sum;
}t[MAXX];

inline int read() {
    int num = 0, f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {num = num * 10 + ch - '0'; ch = getchar();}
    return num * f;
}

void Build(int &u, int x, int l, int r) {
    t[++cnt] = t[u]; 
    u = cnt; ++ t[u].sum;
    if (l == r) return ;
    int mid = (l + r) >> 1;
    if (x <= mid) Build(t[u].l, x, l, mid);
    else Build(t[u].r, x, mid + 1, r);
}

int query(int i, int j, int q, int l, int r) {
    if (r <= q) return t[j].sum - t[i].sum;
    int mid = (l + r) >> 1, temp = query(t[i].l, t[j].l, q, l, mid);
    if (mid < q) temp += query(t[i].r, t[j].r, q, mid + 1, r);
    return temp;
}

int main() {
    n = read(); int x, l, r;
    for (int i = 1; i <= n; ++ i) {
        x = read();
        lst[i] = tp[x];
        tp[x] = i;
    }
    rot[0] = 0;
    for (int i = 1; i <= n; ++ i) {
        rot[i] = rot[i - 1];
        Build(rot[i], lst[i], 0, n);
    }
    m = read();
    for (int i = 1; i <= m; ++ i) {
        l = read(), r = read();
        printf("%d\n", query(rot[l - 1], rot[r], l - 1, 0, n));
    }
    return 0;
}

 

posted @ 2018-08-03 21:00  wakelin  阅读(173)  评论(1编辑  收藏  举报