呜呜,这题做了好久啊。4个月吧。纠结。
以前,自己写的代码和百度来的代码都超时。纠结。
今天,看了下一道类似题的解题报告,就自己动手写了遍。1A,~\(≧▽≦)/~
具体思路:先把N个保存下来,进行离散,然后用就可以用flag记录某个数前面出现的位置,再把询问保存下来,按右端点排序。
对N个数依次处理,删除该数前面出现的,在当前位置插入该数。当处理到第i个位置的数,且询问的右端点也为i是,统计个数。
附上我超挫的线段树代码。
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN 100010
#define MID(a,b) (a+b)>>1
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
struct node{
int num;
int pos;
int opos;
}coo[MAXN];
struct node1{
int cnt,l,r;
}tree[MAXN*4];
struct node2{
int l,r,pos,ans;
}ask[1010];
int flag[MAXN];
void build(int l,int r,int num)
{
tree[num].l = l;
tree[num].r = r;
tree[num].cnt = 0;
if(l==r)
return;
int mid = MID(l,r);
build(l,mid,LL(num));
build(mid+1,r,RR(num));
}
void update(int num)
{
tree[num].cnt = tree[LL(num)].cnt + tree[RR(num)].cnt;
}
bool cmp(node a,node b)
{
return a.num < b.num;
}
bool cmp1(node a,node b)
{
return a.opos < b.opos;
}
bool cmp2(node2 a,node2 b)
{
return a.r < b.r;
}
bool cmp3(node2 a,node2 b)
{
return a.pos < b.pos;
}
void insert(int pos,int num,int chg)
{
if(tree[num].l==tree[num].r)
{
tree[num].cnt = chg;
return;
}
int mid = MID(tree[num].l,tree[num].r);
if(pos<=mid)
insert(pos,LL(num),chg);
else
insert(pos,RR(num),chg);
update(num);
}
int query(int l,int r,int num)
{
if(tree[num].l==l&&tree[num].r==r)
{
return tree[num].cnt;
}
int mid = MID(tree[num].l,tree[num].r);
if(r<=mid)
return query(l,r,LL(num));
else if(l>mid)
return query(l,r,RR(num));
else
return query(l,mid,LL(num)) + query(mid+1,r,RR(num));
}
int main()
{
int n,i,j,q,l;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d",&coo[i].num);
coo[i].opos = i;
}
sort(coo+1,coo+n+1,cmp);
l = 1;
coo[1].pos = 1;
for(i=2;i<=n;i++)
{
while(coo[i].num==coo[i-1].num)
{
coo[i].pos = l;
i++;
if(i>n)
break;
}
if(i>n)
break;
l++;
coo[i].pos = l;
}
sort(coo+1,coo+n+1,cmp1);
// for(i=1;i<=n;i++)
// printf("%d ",coo[i].pos);
// cout<<endl;
memset(flag,-1,sizeof(flag));
scanf("%d",&q);
for(i=0;i<q;i++)
{
scanf("%d%d",&ask[i].l,&ask[i].r);
ask[i].pos = i;
}
sort(ask,ask+q,cmp2);
build(1,n,1);
for(i=1,j=0;i<=n&&j<q;i++)
{
if(flag[coo[i].pos]!=-1)
{
insert(flag[coo[i].pos],1,0);
}
insert(i,1,1);
flag[coo[i].pos] = i;
while(i==ask[j].r)
{
ask[j].ans = query(ask[j].l,ask[j].r,1);
j++;
}
}
sort(ask,ask+q,cmp3);
for(i=0;i<q;i++)
printf("%d\n",ask[i].ans);
}
return 0;
}