您的位置:首页 > 其它

BZOJ1878 [SDOI2009]HH的项链

2018-01-23 18:42 295 查看

NOIP之前写过这题,先用的分块。

#include<bits/stdc++.h>
using namespace std;
const int N=50005;
int t[N+10],a[N+10];
int v[1000005];
int sum=0;
void add(int x)
{
v[x]++;
if(v[x]==1)sum++;
}
void del(int x)
{
v[x]--;
if(v[x]==0)sum--;
}
int sq;
struct node
{
int l,r,id;
bool operator <(const node &b)const
{
if((l/sq)==(b.l/sq))return r<b.r;
return l<b.l;
}
}p[200005];
int ans[200005];
int main()
{
int n;scanf("%d",&n);
sq=sqrt((double)n);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
int m;
scanf("%d",&m);
for(int i=1;i<=m;++i)
{
scanf("%d%d",&p[i].l,&p[i].r);
p[i].id=i;
}
sort(p+1,p+1+m);
int l=0,r=0;
for(int i=1;i<=m;++i)
{
while(r>p[i].r)del(a[r--]);
while(r<p[i].r)add(a[++r]);
while(l<p[i].l)del(a[l++]);
while(l>p[i].l)add(a[--l]);
ans[p[i].id]=sum;
}
for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
return 0;
}

又采用了树状数组,离线按右端点排序,只关心最后一个出现的位置,如果有更新的则将原来的-1将新的位置+1

#include<bits/stdc++.h>
using namespace std;
const int N=50005;
int t[N+10],a[N+10],b[N+10];
int v[N+10];
int lowbit(int x){
return x&(-x);
}
void add(int x,int y)
{
for(;x<=N;x+=lowbit(x))t[x]+=y;
}
int query(int x)
{
int ans=0;for(;x;x-=lowbit(x))ans+=t[x];return ans;
}
struct node
{
int l,r,id;
bool operator <(const node &b)const
{
if(r==b.r)return l<b.l;
return r<b.r;
}
}p[200005];
int ans[200005];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i){scanf("%d",&a[i]);b[i]=a[i];}
sort(b+1,b+1+n);
for(int i=1;i<=n;++i)a[i]=lower_bound(b+1,b+1+n,a[i])-b;
int m;
scanf("%d",&m);
for(int i=1;i<=m;++i)
{
scanf("%d%d",&p[i].l,&p[i].r);
p[i].id=i;
}
sort(p+1,p+1+m);
int pos=1;
for(int i=1;i<=m;++i)
{
while(pos<=p[i].r)
{
if(v[a[pos]])add(v[a[pos]],-1);
v[a[pos]]=pos;add(v[a[pos]],1);pos++;
}
ans[p[i].id]=query(p[i].r)-query(p[i].l-1);
}
for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
return 0;
}

现在我又学了主席树,我们只要对于last(上一次的位置)建主席树,然后查询0~l-1这个区间出现的个数即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
struct node
{
int l,r,s;
}t[N<<2];
int n,m,cnt,last
,pos
,rt
;
void change(int &x,int l,int r,int pos)
{
t[++cnt]=t[x];x=cnt;
if(l==r){t[x].s++;return;}
int mid=l+r>>1;
if(pos<=mid)change(t[x].l,l,mid,pos);
else change(t[x].r,mid+1,r,pos);
t[x].s=t[t[x].l].s+t[t[x].r].s;
return;
}
int query(int x,int y,int l,int r,int L,int R)
{
if(l==L&&r==R)return t[y].s-t[x].s;
int mid=l+r>>1;
if(mid>=R)return query(t[x].l,t[y].l,l,mid,L,R);
else if(mid<L)return query(t[x].r,t[y].r,mid+1,r,L,R);
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);
}
int main()
{
scanf("%d",&n);int x,l,r;
for(int i=1;i<=n;++i)
{
scanf("%d",&x);
last[i]=pos[x];
pos[x]=i;
}
for(int i=1;i<=n;++i)rt[i]=rt[i-1],change(rt[i],0,n,last[i]);
scanf("%d",&m);
for(int i=1;i<=m;++i)
{
scanf("%d%d",&l,&r);
printf("%d\n",query(rt[l-1],rt[r],0,n,0,l-1));
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: