思路分析 : 莫隊基本題目,暴力維護的區間的元素有區間內不一樣元素的出現次數,同時再記錄一下出現不一樣的次數有多少次,記錄一下某個區間不一樣次數的種類,相似鏈表code
複雜度 :某個區間不一樣元素的次數種類最多有 根號n 種,總的複雜度就是 n*sqrt(n)*log(n)htm
寫的時候有個地方寫錯了,就是分塊的排序的地方... 一直TLEblog
代碼示例 :排序
using namespace std; #define ll long long const int maxn = 5e4+5; const int mod = 1e9+7; const double eps = 1e-9; const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; inline int read() { int ret=0,c,f=1; for(c=getchar(); !(isdigit(c)||c=='-'); c=getchar()); if(c=='-') f=-1,c=getchar(); for(; isdigit(c); c=getchar()) ret=ret*10+c-'0'; if(f<0) ret=-ret; return ret; } int n, m; struct node { int zu; int l, r, k, id; bool operator< (const node &v)const{ if (zu == v.zu) return r < v.r; return l < v.l; } }a[maxn]; int pre[maxn], cnt[maxn]; int num[maxn], time2[maxn<<2]; int all; bool pt[maxn<<2]; int ans[maxn]; int gcd(int a, int b){ return b==0?a:gcd(b, a%b); } inline void remove(int x){ cnt[x]--; num[cnt[x]]++, num[cnt[x]+1]--; time2[all++] = cnt[x]; } inline void add(int x){ cnt[x]++; num[cnt[x]]++, num[cnt[x]-1]--; time2[all++] = cnt[x]; } int main() { int l, r, k; cin >> n >> m; int unit = sqrt(n); for(int i = 1; i <= n; i++) pre[i] = read(); for(int i = 1; i <= m; i++){ l = read(), r = read(), k = read(); //scanf("%d%d%d", &l, &r, &k); int f = (l-1)/unit+1; a[i] = {f, l, r, k, i}; } sort(a+1, a+1+m); l = a[1].l, r = a[1].l-1; all = 1; int sum = 0; for(int i = 1; i <= m; i++){ while(l < a[i].l) remove(pre[l++]); while(r > a[i].r) remove(pre[r--]); while(l > a[i].l) add(pre[--l]); while(r < a[i].r) add(pre[++r]); k = 1; sum = 0; for(int j = 1; j < all; j++){ if (!pt[time2[j]] && num[time2[j]] > 0){ if (gcd(time2[j], a[i].k) == 1) { sum += num[time2[j]]; } time2[k++] = time2[j]; pt[time2[j]] = true; } } all = k; ans[a[i].id] = sum; for(int j = 1; j < k; j++) pt[time2[j]] = false; } for(int i = 1; i <= m; i++) printf("%d\n", ans[i]); return 0; }