HackerRank Hiring Contest - D Array and Queries (单调栈思想)

Given an array, you are asked to perform a number of queries and divide the array into what are called, beautifulsubsequences. 

The array  has length . A function  is defined to be a minimal possible , such that it's possible to divide array  into  beautiful subsequences. Note that each element of an array should belong to exactly one subsequence, and subsequence does not necessarily need to be consecutive. 

A subsequence  with length  is called beautiful if and only if: 

  •  or 
  • Let  be a sorted version of . It must hold that  for every 

For instance, if  would be . Because, you can divide  into  beautiful subsequences either like  and  or like  and 

You have to answer  queries. Each query is of the type: 

  •   : you need to change a value of  to , i.e. . Here  is 

After each query, for the value of , lets denote that value as , where  indicates the  query. 

You need to find  modulo .

Input Format

The first line contains a single integer , representing the length of array 
The next line contains the array  given as space-separated integers. 
The next line contains a single integer , representing the number of queries. 
Each of the  lines contain two integers  and , which is described above. 

Constraints

Output Format

Print the required answer in one line. 

Sample Input 0

5
2 2 1 1 1
2
3 2
5 5

Sample Output 0

11

Explanation 0

The initial array  is 

  • After  query the array becomes  this can be divided into  subsequences as  and 
  • After  query the array becomes  this can be divided into  subsequences as  and .

image

Hence, calculating  we get 

Sample Input 1

2
3 3
3
2 4
1 5
2 2

Sample Output 1

9

Explanation 1

The initial array  is 

  • After  query the array becomes  this can be divided into  subsequence as 
  • After  query the array becomes  this can be divided into  subsequence as 
  • After  query the array becomes  this can be divided into  subsequences as  and 

Hence, calculating  we get 



题意:

每次操作变动一个数字。问你这些数字最少分成几个完美数列。

完美数列: 只有一个数字 或者  数字可以重新排列成连续的。


POINT:

用map记录下每个数字的出现次数。

用单调栈的思想来计算答案。

值为x。那么他对答案的贡献是num[x-1]-num[x]。负数则不计。

每次改变的时候只要部分比较就行了。不需要全部重新计算。



#include <iostream>
#include <stdio.h>
#include <cmath>
#include <string.h>
#include <map>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL maxn = 1e6+6;
const LL inf = 0x3f3f3f3f;
const LL mod = 1e9+7;

map<int,int>mp;
map<int,int>temp;

int f(int x)//从left-right
{
	int left=max(x-2,1);
	int right=x+3;
	int num=0;
	for(int i=left+1;i<=right;i++){
		if(mp[i]<mp[i-1])
			num+=mp[i-1]-mp[i];
	}
	return num+mp[right];
}

int a[maxn];
int ans;
int ff(int x)//三个
{
	if(x==1){
		return max(mp[x],mp[x+1]);
	}
	int left=mp[x-1],now=mp[x],right=mp[x+1];
	if(now<left&&now<right){
		return now+left-now+right-now;
	}
	return max(max(now,right),left);
}

int main()
{
	int n;
	scanf("%d",&n);
	int b[maxn];
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		b[i]=a[i];
		mp[a[i]]++;
		temp[a[i]]++;
	}
	sort(b+1,b+1+n);
	int cnt=unique(b+1,b+1+n)-b-1;
	for(int i=1;i<=cnt;i++){
		if(mp[b[i]+1]==0){
			ans+=mp[b[i]];//后面是0。则全要//因为b[i]的值不连续,重点!
		}
		if(mp[b[i]]<mp[b[i]-1]){
			ans+=mp[b[i]-1]-mp[b[i]];
		}
	}
	int q;
	scanf("%d",&q);
	LL aans=0;
	for(int i=1;i<=q;i++){
		int pos,val;
		scanf("%d%d",&pos,&val);
		if(a[pos]==val){

		}else if(abs(a[pos]-val)>2){
			int pre = ff(a[pos])+ff(val);
			mp[a[pos]]--;
			mp[val]++;
			int now = ff(a[pos])+ff(val);
			(ans+=now-pre+mod)%=mod;
		}else{
			int pre = f((a[pos]+val)/2);
			mp[a[pos]]--;
			mp[val]++;
			int now = f((a[pos]+val)/2);
			(ans+=now-pre+mod)%=mod;
		}
		a[pos]=val;
		(aans+=(LL)ans*i%mod)%=mod;
	}
	printf("%lld\n",aans);



}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值