1. 程式人生 > >BZOJ1878 [SDOI2009]HH的項鍊

BZOJ1878 [SDOI2009]HH的項鍊

交到洛谷上只有80分。。。 注意初始值 l = 1, r = 0 然後就是修改的部分(revise) 我套用了之前的習慣,直接傳值進去,直接+=k 然後判斷是否為1或者0,但是我沒有想到1可以是0+1得來也可以是2-1得來 所以想安全一點就寫if和else吧。。。有時候真的難以想到這種可能 指標移動的時候注意,每次移動前,l和r所在的點已經被算入答案,如果l現在的點不是所在區間裡的,直接移動 如果l是所在區間裡的(l > que[i].l)那麼不能直接先修改再移動l,這樣l就算了兩次,應該先移動l再修改或者說修改的是l-1,然後移動l

#include <algorithm>
#include
<iostream>
#include <cstring> #include <cstdio> #include <cmath> using namespace std; #define debug(x) cerr << #x << "=" << x << endl; const int MAXN = 1000000 + 10; int n,m,ans,a[MAXN],f[MAXN],blo_be[MAXN]; struct query{ int l, r, id, val; }que[MAXN]; bool cmp
(query a, query b) { return blo_be[a.l] == blo_be[b.l] ? a.r < b.r : a.l < b.l; } bool cmp_id(query a, query b) { return a.id < b.id; } void revise(int col, int k) { if(k == 1) { f[col]++; if(f[col] == 1) ans++; } else { f[col]--; if(!f[col]) ans--; } } int main() { scanf
("%d", &n); for(int i=1; i<=n; i++) { scanf("%d", &a[i]); } scanf("%d", &m); for(int i=1; i<=m; i++) { scanf("%d%d", &que[i].l, &que[i].r); que[i].id = i; } int unit = sqrt(n); for(int i=1; i<=n; i++) { blo_be[i] = i / unit + 1; } sort(que+1, que+m+1, cmp); int l = 1, r = 0; for(int i=1; i<=m; i++) { int ql = que[i].l, qr = que[i].r; while(l < ql) revise(a[l], -1), l++; while(l > ql) revise(a[l-1], 1), l--; while(r < qr) revise(a[r+1], 1), r++; while(r > qr) revise(a[r], -1), r--; que[i].val = ans; } sort(que+1, que+m+1, cmp_id); for(int i=1; i<=m; i++) { printf("%d\n", que[i].val); } return 0; }