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; }