hdu 多校contest4 group(树状数组)


树状数组 线段树 again- -又不会处理 again- -

看了网上其他人的思路:


就是 要找出最少的分组 分组以数值连续为标准


还是以 右端点 为关键点

sum(i)为从 1~i(输入数下标)的最少分组个数


从左向右  不断的更新 r(i)

从第一个数开始扫描  当前数a[i]所对应的 i 向上update(i,1)加1 

如果 在 i之前 1~i-1中的 数中有 a[i]+1 a[i]-1 则,这两个数 所在pos[a[i]+1], pos[a[i]-1】分别 向上update(pos,-1) 减1

(其实就是每扫描到一个新的数,在这个数上 加一个组,若之前有和它相邻的数,则和他相邻的数的位置要告诉自己和它的boss自己可以归在最新的那个组,自己和管理它的boss都要减少一组)


边更新边计算query的值 即 如果 i==query[].r (query的值 以 r的 非递减顺序存储)

query的时候 就 用 sum(r)-sum(l)


ok .其实还不是很理解


上code.


#include <iostream>
#include <string.h>
#include <algorithm>

using namespace std;

const int MAXN=100010;
int n,m,a[MAXN],c[MAXN],pos[MAXN],ans[MAXN];

struct node
{
	int l,r,id;
}query[MAXN];

bool cmp(struct node a,struct node b)
{
	return a.r<b.r;
}

int lowbit(int x)
{
	return x&(-x);
}

void update(int i,int val)
{
	while(i<=n)
	{
		c[i]+=val;
		i+=lowbit(i);
	}
}

int sum(int a,int b)
{
	int ar=0,br=0;
	while(a)
	{
		ar+=c[a];
		a-=lowbit(a);
	}
	while(b)
	{
		br+=c[b];
		b-=lowbit(b);
	}
	return (br-ar);
}

int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		int i,k=1;
		for (i = 1; i <= n; i++) {
			cin>>a[i];
			pos[a[i]]=i;
		}
		for(i = 1;i <= m; i++){
			cin>>query[i].l>>query[i].r;
			query[i].id=i;
		}
		sort(query+1,query+1+m,cmp);
		for (i = 1; i <= n; i++) {
			update(a[i],1);
			if(a[i]<n && pos[a[i]+1]<i)
			  update(pos[a[i]+1],-1);
			if(a[i]>1 && pos[a[i]-1]<i)
			  update(pos[a[i]-1],-1);
			while(k<=m && query[k].r==i)
			{
				ans[query[k].id]=sum(query[k].l,query[k].r);
				k++;
			}

		}
		for(i = 1; i <= m; ++i){
			cout<<ans[i]<<endl;
		}

	}
	return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值