1. 程式人生 > >【BZOJ】1878: [SDOI2009]HH的項鏈 (主席樹)

【BZOJ】1878: [SDOI2009]HH的項鏈 (主席樹)

莫隊 color amp span void == 常數 不同 d+

題目

傳送門:QWQ


分析

莫隊也能做,但我想練練主席樹。

求k-th一樣維護第i個時候的線段樹,線段樹來維護區間不同數。

然後查詢時可以通過上下界小優化一波。

但是我的代碼醜陋無比,常數巨大(捂臉


代碼

技術分享圖片
#include <bits/stdc++.h>
using namespace std;

const int maxn=50007;
int ls[maxn<<6], rs[maxn<<6], sum[maxn<<6], newp, root[maxn<<6];
int last[1000007
]; inline int in() { 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; } void add(int l,int r,int x,int& cur,int cur1,int val) { cur=++newp; ls[cur]=ls[cur1]; rs[cur]=rs[cur1];//
root[i]=root[i-1] sum[cur]=sum[cur1]+val; if(l==r) return; int mid=l+r>>1; if(x<=mid) add(l,mid,x,ls[cur],ls[cur1],val); else add(mid+1,r,x,rs[cur],rs[cur1],val); } int query(int l,int r,int cnt,int cnt1,int L) { if(l>=L) return sum[cnt1]-sum[cnt];
int mid=l+r>>1,ans=0; if(mid>=L) ans+=query(l,mid,ls[cnt],ls[cnt1],L); ans+=query(mid+1,r,rs[cnt],rs[cnt1],L); return ans; } int main() { int n=in(); for(int i=1;i<=n;i++) { int x,temp; x=in(); if(last[x]) { add(1,n,last[x],root[i],root[i-1],-1); add(1,n,i,root[i],root[i],1); } else { add(1,n,i,root[i],root[i-1],1); } last[x]=i; } int q; q=in(); for(int i=1;i<=q;i++) { int l,r; l=in(); r=in(); printf("%d\n",query(1,n,root[l-1],root[r],l)); } }
View Code

【BZOJ】1878: [SDOI2009]HH的項鏈 (主席樹)