BZOJ 1878: [SDOI2009]HH的項鏈
阿新 • • 發佈:2018-03-15
node post spa 樹狀 for 描述 個數 圖片 etc
題目描述
num[i]表示在[l,r]內數字i的個數
當區間變為[l±1,r]或,[l,r±1]的時候,num[i]由0變為1或由1變為0時答案才會變化
#include<complex> #include<cstdio> #include<algorithm> using namespace std; const int N=5e4+7; struct node{ int l,r,id; }q[N<<2]; int n,m; int ans[N<<2],a[N],num[N*20],pos[N]; int qread() {莫隊int x=0; char ch=getchar(); while(ch<‘0‘ || ch>‘9‘)ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x; } bool cmp(const node &a,const node &b) { if(pos[a.l]==pos[b.l])return a.r<b.r; return pos[a.l]<pos[b.l]; } void change(int&tot,int id,int add) { if(add) { if(!num[a[id]]) tot++; num[a[id]]++; return; } num[a[id]]--; if(!num[a[id]])tot--; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) a[i]=qread(); scanf("%d",&m); for(inti=1;i<=m;i++) { q[i].l=qread();q[i].r=qread(); q[i].id=i; } int tmp=sqrt(n); for(int i=1;i<=n;i++) pos[i]=(i-1)/tmp+1; sort(q+1,q+m+1,cmp); int l=1,r=0,tot=0; for(int i=1;i<=m;i++) { while(l<q[i].l) change(tot,l++,0); while(l>q[i].l) change(tot,--l,1); while(r<q[i].r) change(tot,++r,1); while(r>q[i].r) change(tot,r--,0); ans[q[i].id]=tot; } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }
也可以用離線算法+樹狀數組來做這道題
用nxt[i]來記錄與第i個數相同的上一個數的位置
將詢問的區間按左端點進行排序
用一個指針l指向當前區間的左端點,當l向右移動時,第l個數就不在查詢的區間內了,這時就將樹狀數組中nxt[l]位置上的數+1(自己舉個例子就比較好理解了)
#include<complex> #include<cstdio> #include<algorithm> using namespace std; const int N=5e4+7; struct node{ int l,r,id; }q[N<<2]; int n,m; int c[N],nxt[N],pre[N*20],ans[N<<2]; int qread() { int x=0; char ch=getchar(); while(ch<‘0‘ || ch>‘9‘)ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x; } inline int Lowbit(int x) { return x&-x; } inline int Add(int x,int v) { for(;x<=n;x+=Lowbit(x)) c[x]+=v; } inline int Sum(int x) { int ans=0; for(;x;x-=Lowbit(x)) ans+=c[x]; return ans; } bool cmp(const node &a,const node &b) { return a.l<b.l; } int main() { scanf("%d",&n); int x; for(int i=1;i<=n;i++) { x=qread(); nxt[pre[x]]=i; if(!pre[x])Add(i,1); pre[x]=i; } scanf("%d",&m); for(int i=1;i<=m;i++) { q[i].l=qread();q[i].r=qread(); q[i].id=i; } sort(q+1,q+m+1,cmp); int l=1; for(int i=1;i<=m;i++) { while(l<q[i].l) { if(nxt[l]) Add(nxt[l],1); l++; } ans[q[i].id]=Sum(q[i].r)-Sum(q[i].l-1); } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }樹狀數組
BZOJ 1878: [SDOI2009]HH的項鏈