This problem can is solve in simpler o(nsqrtn) solution, but I'll describe O( nlogn) one.
We'll solve this problem in offline. for eachx (0?≤? ) x? <? n)we should keep all the queries so end inx. Iterate thatxFrom 0 to n?-? 1. Also we need to keep some arrayDsuch .x Dl? +? D l. +?1? +?...? +? D x Would be is the answer for query[l; X]. To keepDcorrect, before the processing all queries so end inx, we need to updateD. LetTBeing the current integer inA, i. E. Ax , and VectorPBe the list of indices of previous occurences ofT(0-based numeration of Vector). Then, if| P|? ≥? T , you need to add1 to DP[| P|? -? T] , because this position are now the first ( from right) that contains exactlyToccurences ofT. After, if| P|? ? T , you need to subtract2 from DP[| P|? -? T?-? 1] , in order to close current interval and cancel previous. Finally, if| P|? ? t? +?1, then you need additionally add1 to DP[| P|? -? T?-? 2] To cancel previous close of the interval.
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include < iostream> #include <iomanip> #include <cmath> #include <map> #include <set> #include < queue>using namespace std; #define LS (RT) Rt*2#define RS (RT) Rt*2+1#define ll long long#define ull unsigned long long#de Fine Rep (I,s,e) for (int. i=s;i<e;i++) #define REPE (i,s,e) for (int i=s;i<=e;i++) #define CL (A, B) memset (A,b,sizeof (A )) #define IN (s) freopen (S, "R", stdin) #define OUT (s) freopen (S, "w", stdout) const int MAXN = 1e5+100;int N,m;int a[maxn],c[ maxn],ans[maxn];struct query{int l,r,id; BOOL operator < (const Query &t) const {return R<T.R;}} q[maxn];inline int lowbit (int x) {return x& (-X);} void Add (int i, int v) {while (i<=n) {c[i]+=v; I+=lowbit (i); }}int sum (int x) {int ret=0; while (x>0) {ret+=c[x]; X-=lowbit (x); } return ret;} int main () {int sz; while (~SCANF ("%d%d", &n,&amP;m)) {vector<int>data[maxn]; CL (c,0); for (int i=1;i<=n;i++) scanf ("%d", &a[i]); for (int i=1;i<=m;i++) {scanf ("%d%d", &Q[I].L,&Q[I].R); Q[i].id=i; } sort (q+1,q+1+m); for (int i=1,k=1;i<=n;i++) {if (a[i]<=n) {data[a[i]].push_back (i); Sz=data[a[i]].size (); if (Sz>=a[i]) {Add (data[a[i]][sz-a[i]],1); if (Sz>a[i]) Add (data[a[i]][sz-a[i]-1],-2); if (sz>a[i]+1) Add (data[a[i]][sz-a[i]-2],1); }} while (Q[k].r==i && k<=m) {ans[q[k].id]=sum (Q[K].R)-sum (q[k ].L-1); k++; }} for (int i=1;i<=m;i++) printf ("%d\n", Ans[i]); } return 0;}
Code for debugging understanding and adding gaze
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include < iostream> #include <iomanip> #include <cmath> #include <map> #include <set> #include < queue>using namespace std; #define LS (RT) Rt*2#define RS (RT) Rt*2+1#define ll long long#define ull unsigned long long#de Fine Rep (I,s,e) for (int. i=s;i<e;i++) #define REPE (i,s,e) for (int i=s;i<=e;i++) #define CL (A, B) memset (A,b,sizeof (A )) #define IN (s) freopen (S, "R", stdin) #define OUT (s) freopen (S, "w", stdout) const int MAXN = 1e5+100;int N,m;int a[maxn],c[ maxn],ans[maxn];struct query{int l,r,id; BOOL operator < (const Query &t) const {return R<T.R;}} q[maxn];inline int lowbit (int x) {return x& (-X);} void Add (int i, int v) {while (i<=n) {c[i]+=v; I+=lowbit (i); }}int sum (int x) {int ret=0; while (x>0) {ret+=c[x]; X-=lowbit (x); } return ret;} int main () {int sz; while (~SCANF ("%d%d", &n,&amP;m)) {vector<int>data[maxn]; CL (c,0); for (int i=1;i<=n;i++) scanf ("%d", &a[i]); for (int i=1;i<=m;i++) {scanf ("%d%d", &Q[I].L,&Q[I].R); Q[i].id=i; } sort (q+1,q+1+m); for (int i=1,k=1;i<=n;i++) {if (a[i]<=n) {data[a[i]].push_back (i); Sz=data[a[i]].size (); if (Sz>=a[i]) {Add (data[a[i]][sz-a[i]],1),///From right to left A[i] times A[i] position +1 if (Sz>a[i]) Add (data[a[i]][sz-a[i]-1],-2); From right to left a[i]+1 A[i] Position-2,//due to sz==a[i], this position has been added 1. This time I was read. The position of a[i] from right to left A[i] is also + 1. Then the position of the query a[i]+1 appears a[i] to I. The answer is -2+1+1=0,//query a[i] The position of a[i] to I, the answer is 1 if (sz>a[i]+1) Add (Data[a[i]][sz-a[i]-2], 1); From right to left a[i]+2 times appears a[i] position +1, before being + 1-2, so becomes 0 These three lines of code are maintained, from the current I to the left number, a[i] times appear a[i] position always 1//a[i]+1 occurrences A[i] position always 1, a[i]+2 and many other times the position is always 0, which The query results for the interval with I as the right endpoint are all right}} while (Q[k].r==i && k<=m) { printf ("#i =%d#\n", i); for (int j=0;j<=n;j++) printf ("c[%d]=%d\n", J,c[j]); Ans[q[k].id]=sum (Q[K].R)-sum (Q[K].L-1); k++; }} for (int i=1;i<=m;i++) printf ("%d\n", Ans[i]); } return 0;}
Codeforces 220b-little Elephant and array offline tree array