【[HEOI2012]採花】
阿新 • • 發佈:2019-01-02
\(HH\)的項鍊加強版,資料範圍和題意都加強了
題意大概:給出n個數,求區間出現次數>=2的數的個數。
一眼莫隊,可是我還不會莫隊啊
那就樹狀陣列吧
回憶一下\(HH\)的項鍊,套路差不多,那道題我們維護的是每一種顏色最後出現的位置,因為根據其最後出現的位置我們就可以判斷其是否在區間裡
而判斷這道題也很簡單,我們維護每一個顏色倒數第二次出現是在什麼位置,這樣就能判斷其是否出現次數大於等於二了
還是離線+樹狀陣列就可以啦
程式碼
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define re register #define lowbit(x) ((x)&(-x)) #define maxn 2000005 inline int read() { char c=getchar(); int x=0; while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar(); return x; } int c[2][maxn]; int n,m,T; struct Ask { int l,r,rk; }q[maxn]; inline int cmp(Ask K,Ask M) { return K.r<M.r; } inline void add(int x,int o,int val) { for(re int i=x;i<=n;i+=lowbit(i)) c[o][i]+=val; } inline int ask(int x,int o) { int ans=0; for(re int i=x;i;i-=lowbit(i)) ans+=c[o][i]; return ans; } int a[maxn],pre[maxn],col_p[maxn],Ans[maxn]; int main() { n=read(),T=read(),m=read(); for(re int i=1;i<=n;i++) a[i]=read(); for(re int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].rk=i; std::sort(q+1,q+m+1,cmp); for(re int i=1;i<=n;i++) pre[i]=col_p[a[i]],col_p[a[i]]=i; int now=1; for(re int i=1;i<=n;i++) { if(!pre[i]) add(i,0,1); else { if(!pre[pre[i]]) add(i,0,1),add(pre[i],1,1),add(pre[i],0,-1); else { add(i,0,1),add(pre[i],0,-1); add(pre[i],1,1),add(pre[pre[i]],1,-1); } } while(i==q[now].r) Ans[q[now].rk]=ask(q[now].r,1)-ask(q[now].l-1,1),now++; } for(re int i=1;i<=m;i++) printf("%d\n",Ans[i]); return 0; }