2 3 1 1 4 2 1 2 2 3 5 1 1 2 1 3 3 1 5 2 4 3 5
1 5 6 36
此题和 hdu 4358 Boring counting 类似,可以说是hdu4358的简化版,
具体可以看http://blog.csdn.net/jtjy568805874/article/details/43925895
树状数组的解法有两种:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<vector> #include<map> using namespace std; const int maxn = 100005; const int low(int x){ return x&-x; } map<int, int> M, N; int T, n, k, a[maxn], p[maxn], m; long long f[maxn], ans[maxn]; struct abc { int a, b, c; bool operator <(const abc&x) { if (x.c == c) return b < x.b; return c < x.c; } }r[maxn]; void add(int x, long long y) { for (int i = x; i <= n; i += low(i)) f[i] += y; } long long sum(int x) { long long tot = 0; for (; x; x -= low(x)) tot += f[x]; return tot; } int main() { scanf("%d", &T); while (T--) { cin >> n; int x, y = 0; M.clear(); N.clear(); memset(f, 0, sizeof(f)); memset(p, 0, sizeof(p)); for (int i = 1; i <= n; i++) { scanf("%d", &x); if (M.count(x)) a[i] = M[x]; else { a[i] = M[x] = ++y; N[y] = x; } } scanf("%d", &m); for (int i = 1; i <= m; r[i].a = i++) scanf("%d%d", &r[i].b, &r[i].c); sort(r + 1, r + m + 1); for (int i = 1, j = 1; i <= n&&j <= m; i++) { if (p[a[i]]) add(p[a[i]], -N[a[i]]); p[a[i]] = i; add(p[a[i]], N[a[i]]); for (; j <= m&&r[j].c == i; j++) ans[r[j].a] = sum(r[j].c) - sum(r[j].b - 1); } for (int i = 1; i <= m; i++) cout << ans[i] << endl; } return 0; }第二种,同hdu4358.#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<vector> #include<map> using namespace std; const int maxn = 100005; const int low(int x){ return x&-x; } map<int, int> M, N; int T, n, k, a[maxn], p[maxn], m; long long f[maxn], ans[maxn]; struct abc { int a, b, c; bool operator <(const abc&x) { if (x.c == c) return b < x.b; return c < x.c; } }r[maxn]; void add(int x, long long y) { for (int i = x; i <= n; i += low(i)) f[i] += y; } long long sum(int x) { long long tot = 0; for (; x; x -= low(x)) tot += f[x]; return tot; } int main() { scanf("%d", &T); while (T--) { cin >> n; int x, y = 0; M.clear(); N.clear(); memset(f, 0, sizeof(f)); memset(p, 0, sizeof(p)); for (int i = 1; i <= n; i++) { scanf("%d", &x); if (M.count(x)) a[i] = M[x]; else { a[i] = M[x] = ++y; N[y] = x; } } scanf("%d", &m); for (int i = 1; i <= m; r[i].a = i++) scanf("%d%d", &r[i].b, &r[i].c); sort(r + 1, r + m + 1); for (int i = 1, j = 1; i <= n&&j <= m; i++) { add(p[a[i]] + 1, N[a[i]]); p[a[i]] = i; add(p[a[i]] + 1, -N[a[i]]); for (; j <= m&&r[j].c == i; j++) ans[r[j].a] = sum(r[j].b); } for (int i = 1; i <= m; i++) cout << ans[i] << endl; } return 0; }
zkw线段树
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<vector> #include<map> using namespace std; const int maxn = 100005; const int low(int x){ return x&-x; } map<int, int> M, N; int T, n, k, a[maxn], p[maxn], m, u; long long f[maxn], ans[maxn]; struct abc { int a, b, c; bool operator <(const abc&x) { if (x.c == c) return b < x.b; return c < x.c; } }r[maxn]; void change(int x, int y) { x += u; f[x] = y; for (x >>= 1; x; x >>= 1) f[x] = f[x + x] + f[x + x + 1]; } long long find(int l, int r) { long long tot = 0; for (l += u - 1, r += u + 1; l ^ r ^ 1; l >>= 1, r >>= 1) { if (~l & 1) tot += f[l ^ 1]; if ( r & 1) tot += f[r ^ 1]; } return tot; } int main() { scanf("%d", &T); while (T--) { cin >> n; for (u = 1; u < n; u += u); int x, y = 0; M.clear(); N.clear(); memset(f, 0, sizeof(f)); memset(p, 0, sizeof(p)); for (int i = 1; i <= n; i++) { scanf("%d", &x); if (M.count(x)) a[i] = M[x]; else { a[i] = M[x] = ++y; N[y] = x; } } scanf("%d", &m); for (int i = 1; i <= m; r[i].a = i++) scanf("%d%d", &r[i].b, &r[i].c); sort(r + 1, r + m + 1); for (int i = 1, j = 1; i <= n&&j <= m; i++) { if (p[a[i]]) change(p[a[i]], 0); p[a[i]] = i; change(p[a[i]], N[a[i]]); for (; j <= m&&r[j].c == i; j++) ans[r[j].a] = find(r[j].b, r[j].c); } for (int i = 1; i <= m; i++) cout << ans[i] << endl; } return 0; }