您的位置:首页 > 大数据 > 人工智能

【树状数组】2016 BUPT Winter Training #2 D

2016-02-10 05:05 399 查看
这个题可以理解是求一个区间有多少个不同的数,离线来做

从后往前做,每来一个数,更新这个数的位置,然后用树状数组维护前缀和。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;

int n,m;
int c[200100],loc[300100];

bool flag[300100];
struct rec
{
int x,y,t,ans;
}query[200100];
struct rec2
{
int da,w,wei;
}a[300100];
int lowbit(int x) {return x&(-x);}
void insert(int x,int w)
{
while (x<=n)
{
c[x]+=w;
x+=lowbit(x);
}
}
int get_sum(int x)
{
int now=0;
while (x>0)
{
now+=c[x];
x-=lowbit(x);
}
return now;
}
int cmp1(rec a,rec b)
{
return a.x>b.x;
}
int cmp2(rec a,rec b)
{
return a.t<b.t;
}
int cmp3(rec2 a,rec2 b)
{
return a.da<b.da;
}
int cmp4(rec2 a,rec2 b)
{
return a.wei<b.wei;
}
int main()
{
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
memset(flag,0,sizeof(flag));
memset(a,0,sizeof(a));
memset(query,0,sizeof(query));
memset(loc,0,sizeof(loc));
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i].da);
a[i].wei=i;
}
sort(a+1,a+n+1,cmp3);
a[1].w=1;
int now=1;
for (int i=2;i<=n;i++)
{
if (a[i].da!=a[i-1].da) now++;
a[i].w=now;
}
sort(a+1,a+n+1,cmp4);
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&query[i].x,&query[i].y);
query[i].t=i;
}
sort(query+1,query+m+1,cmp1);
int head=1;
for (int i=n;i;i--)
{
if (flag[a[i].w]) insert(loc[a[i].w],-1);
else flag[a[i].w]=true;
insert(i,1);
loc[a[i].w]=i;
while (query[head].x==i)
{
query[head].ans=get_sum(loc[a[query[head].y+i-1].w]);
head++;
}
}
sort(query+1,query+m+1,cmp2);
for (int i=1;i<=m;i++)
printf("%d\n",query[i].ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: