spoj ADACROP - Ada and Harvest(分块+离散化)

这篇博客介绍了如何利用数据结构中的分块和离散化技术来解决Ada在农场收割蔬菜的问题。在收割过程中,每当Ada替换一种蔬菜时,她想知道新种植的蔬菜在其之前有多少与其相同种类的蔬菜。输入包含作物的数量和收割次数,以及每个位置的蔬菜类型。输出为每次收割后,新蔬菜前相同种类蔬菜的数量。博客提供了示例输入和输出,并解释了如何通过离散化和分块策略高效处理这个问题。
摘要由CSDN通过智能技术生成

ADACROP - Ada and Harvest

#datastructures

 

As you might already know, Ada the Ladybug is a farmer. She has a very long furrow with many kinds of vegetables (represented by integer numbers). Whenever she wants to harvest a single vegetable, she always replace it with anoher vegetable (possibly same kind).

After each replacement, she wants to know the number of vegetables of the same kind (at the new vegetable) which are before it (have lower possition in furrow).

 

Input

The first line of input containts 1 ≤ N, Q ≤ 2*105 , the length of furrow and number of harvests.

The next line contains numbers 0 ≤ Ai ≤ 109 the kind of vegetable which is currently on ith spot in furrow (indexed from 0).

The next Q lines contains two numbers 0 ≤ i < N (the index of harvested plant) and 0 ≤ a ≤ 109 (the kind of newly planted vegetable)

Output

For each harvest, print the number of vegetables of the same kind before the newly planted vegetable.

Example Input

5 5
1 2 1 2 1
2 2
4 2
2 3
3 3
4 3

Example Output

1
3
0
1
2

Example Input 2

10 10
2 3 5 3 9 3 5 2 9 9
7 2
0 5
0 2
1 2
9 2
4 3
8 2
4 2
2 5
3 5

Example Output 2

1
0
0
1
3
1
3
2
0
1

对于一个序列修改某个数,之后再查询前面的数当中与新的数相等的个数。由于数值的范围到了1e9,但是数量只有4e5,所以使用离散化,再进行分块预处理查询。

#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
int a[MAXN],x[MAXN],y[MAXN],rank[2*MAXN],mp[448][2*MAXN];
struct node{
	int v,id;
}b[2*MAXN];
bool cmp(node A,node B)
{
	return A.v<B.v;
}
int main()
{
	int n,q;
	scanf("%d%d",&n,&q);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
		b[i].v=a[i];
		b[i].id=i;
	}
	for(int i=0;i<q;i++)
	{
		scanf("%d%d",&x[i],&y[i]);
		b[n+i].v=y[i];
		b[n+i].id=n+i;
	}
	sort(b,b+n+q,cmp);
	rank[b[0].id]=0;
	for(int i=1;i<n+q;i++)
	{
		if(b[i].v==b[i-1].v)
			rank[b[i].id]=rank[b[i-1].id];
		else
			rank[b[i].id]=rank[b[i-1].id]+1;		
	}
	for(int i=0;i<n;i++)
		a[i]=rank[i];
	int sz=(int)sqrt(n);
	int rem=n%sz;
	int num;
	if(rem==0)
		num=n/sz;
	else
		num=n/sz+1;
	memset(mp,0,sizeof(mp));
	for(int i=0;i<num;i++)
		for(int j=0;j<sz&&i*sz+j<n;j++)
			mp[i][a[i*sz+j]]++;
	for(int i=0;i<q;i++)
	{
		int g=x[i],h=rank[n+i];
		
		int pos;
		if((g+1)%sz==0)
			pos=(g+1)/sz-1;
		else
			pos=(g+1)/sz;
		
		int ans=0;
		for(int j=0;j<pos;j++)
			ans+=mp[j][h];
		for(int j=pos*sz;j<g;j++)
			if(a[j]==h)
				ans++;
		printf("%d\n",ans);
		mp[pos][a[g]]--;
		mp[pos][h]++;
		a[g]=h;
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值