题目大意:给出一个数列,问[x,y]中间有多少种不同的数字在[a,b]之间。
思路:又是傻逼莫队……
如果没有[a,b]的限制,那么就是傻逼莫队了
这个限制就比较坑爹了,当然常规一点的想法还是树套树,很明显这个空间限制是卡树套树的。
所以就只能莫队了。然而暴力的求[a,b]之间有多少个数的话时间就到了O(n^2),但是利用一下分块,时间复杂度就是O(n*sqrt(n))了。
CODE:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define SIZE 350 #define MAX 100010 using namespace std; namespace IStream{ const int L=1<<15; char buffer[L],*S,*T; inline char Get_Char() { if(S==T) { T=(S=buffer)+fread(buffer,1,L,stdin); if(S==T) return EOF; } return *S++; } inline int GetInt() { char c; int re=0; for(c=Get_Char();c<'0'||c>'9';c=Get_Char()); while(c>='0'&&c<='9') re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char(); return re; } } int size; int cnt,asks; int src[MAX],belong[MAX]; int begin[SIZE]; struct Ask{ int x,y,a,b; int id; bool operator <(const Ask &a)const { if(belong[x] == belong[a.x]) return y < a.y; return x < a.x; } void Read(int p) { x = IStream::GetInt(); y = IStream::GetInt(); a = IStream::GetInt(); b = IStream::GetInt(); id = p; } }ask[1000010]; int colors[MAX],num[SIZE]; int ans[1000010]; inline void Add(int col) { if(!colors[col]) ++num[belong[col]]; ++colors[col]; } inline void Del(int col) { if(colors[col] == 1) --num[belong[col]]; --colors[col]; } inline int Query(int a,int b) { int re = 0; if(belong[a] == belong[b]) { for(int i = a; i <= b; ++i) re += colors[i] ? 1:0; return re; } int l = belong[a] + 1,r = belong[b] - 1; for(int i = l; i <= r; ++i) re += num[i]; for(int i = a; belong[i] == belong[a]; ++i) re += colors[i] ? 1:0; for(int i = begin[belong[b]]; i <= b; ++i) re += colors[i] ? 1:0; return re; } int main() { cin >> cnt >> asks; size = sqrt(cnt); for(int i = 1; i <= cnt; ++i) { belong[i] = i / size; if(!begin[belong[i]]) begin[belong[i]] = i; } for(int i = 1; i <= cnt; ++i) src[i] = IStream::GetInt(); for(int i = 1; i <= asks; ++i) ask[i].Read(i); sort(ask + 1,ask + asks + 1); int l = 1,r = 0; for(int i = 1; i <= asks; ++i) { while(r < ask[i].y) Add(src[++r]); while(l > ask[i].x) Add(src[--l]); while(r > ask[i].y) Del(src[r--]); while(l < ask[i].x) Del(src[l++]); ans[ask[i].id] = Query(ask[i].a,ask[i].b); } for(int i = 1; i <= asks; ++i) printf("%d\n",ans[i]); return 0; }