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

BZOJ1878 [SDOI2009]HH的項鏈

ace ast truct pac const 排序 位置 新的 include

NOIP之前寫過這題,先用的分塊。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=50005;
 4 int t[N+10],a[N+10];
 5 int v[1000005];
 6 int sum=0;
 7 void add(int x)
 8 {
 9     v[x]++;
10     if(v[x]==1)sum++;
11 }
12 void del(int x)
13 {
14     v[x]--;
15     if(v[x]==0)sum--;
16 }
17 int
sq; 18 struct node 19 { 20 int l,r,id; 21 bool operator <(const node &b)const 22 { 23 if((l/sq)==(b.l/sq))return r<b.r; 24 return l<b.l; 25 } 26 }p[200005]; 27 int ans[200005]; 28 int main() 29 { 30 int n;scanf("%d",&n); 31 sq=sqrt((double)n);
32 for(int i=1;i<=n;++i)scanf("%d",&a[i]); 33 int m; 34 scanf("%d",&m); 35 for(int i=1;i<=m;++i) 36 { 37 scanf("%d%d",&p[i].l,&p[i].r); 38 p[i].id=i; 39 } 40 sort(p+1,p+1+m); 41 int l=0,r=0; 42 for(int i=1;i<=m;++i)
43 { 44 while(r>p[i].r)del(a[r--]); 45 while(r<p[i].r)add(a[++r]); 46 while(l<p[i].l)del(a[l++]); 47 while(l>p[i].l)add(a[--l]); 48 ans[p[i].id]=sum; 49 } 50 for(int i=1;i<=m;++i)printf("%d\n",ans[i]); 51 return 0; 52 }

又采用了樹狀數組,離線按右端點排序,只關心最後一個出現的位置,如果有更新的則將原來的-1將新的位置+1

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=50005;
 4 int t[N+10],a[N+10],b[N+10];
 5 int v[N+10];
 6 int lowbit(int x){
 7     return x&(-x);
 8 }
 9 void add(int x,int y)
10 {
11     for(;x<=N;x+=lowbit(x))t[x]+=y;
12 }
13 int query(int x)
14 {
15     int ans=0;for(;x;x-=lowbit(x))ans+=t[x];return ans;
16 }
17 struct node
18 {
19     int l,r,id;
20     bool operator <(const node &b)const
21     {
22         if(r==b.r)return l<b.l;
23         return r<b.r;
24     }
25 }p[200005];
26 int ans[200005];
27 int main()
28 {
29     int n;
30     scanf("%d",&n);
31     for(int i=1;i<=n;++i){scanf("%d",&a[i]);b[i]=a[i];}
32     sort(b+1,b+1+n);
33     for(int i=1;i<=n;++i)a[i]=lower_bound(b+1,b+1+n,a[i])-b;
34     int m;
35     scanf("%d",&m);
36     for(int i=1;i<=m;++i)
37     {
38         scanf("%d%d",&p[i].l,&p[i].r);
39         p[i].id=i;
40     }
41     sort(p+1,p+1+m);
42     int pos=1;
43     for(int i=1;i<=m;++i)
44     {
45         while(pos<=p[i].r)
46         {
47             if(v[a[pos]])add(v[a[pos]],-1);
48             v[a[pos]]=pos;add(v[a[pos]],1);pos++;
49         }
50         ans[p[i].id]=query(p[i].r)-query(p[i].l-1);
51     }
52     for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
53     return 0;
54 }

現在我又學了主席樹,我們只要對於last(上一次的位置)建主席樹,然後查詢0~l-1這個區間出現的個數即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e6+10;
 4 struct node
 5 {
 6     int l,r,s;
 7 }t[N<<2];
 8 int n,m,cnt,last[N],pos[N],rt[N];
 9 void change(int &x,int l,int r,int pos)
10 {
11     t[++cnt]=t[x];x=cnt;
12     if(l==r){t[x].s++;return;}
13     int mid=l+r>>1;
14     if(pos<=mid)change(t[x].l,l,mid,pos);
15     else change(t[x].r,mid+1,r,pos);
16     t[x].s=t[t[x].l].s+t[t[x].r].s;
17     return;
18 }
19 int query(int x,int y,int l,int r,int L,int R)
20 {
21     if(l==L&&r==R)return t[y].s-t[x].s;
22     int mid=l+r>>1;
23     if(mid>=R)return query(t[x].l,t[y].l,l,mid,L,R);
24     else if(mid<L)return query(t[x].r,t[y].r,mid+1,r,L,R);
25     return query(t[x].l,t[y].l,l,mid,L,mid)+query(t[x].r,t[y].r,mid+1,r,mid+1,R);
26 }
27 int main()
28 {
29     scanf("%d",&n);int x,l,r;
30     for(int i=1;i<=n;++i)
31     {
32         scanf("%d",&x);
33         last[i]=pos[x];
34         pos[x]=i;
35     }
36     for(int i=1;i<=n;++i)rt[i]=rt[i-1],change(rt[i],0,n,last[i]);
37     scanf("%d",&m);
38     for(int i=1;i<=m;++i)
39     {
40         scanf("%d%d",&l,&r);
41         printf("%d\n",query(rt[l-1],rt[r],0,n,0,l-1));
42     }
43     return 0;
44 }

BZOJ1878 [SDOI2009]HH的項鏈