3236: [Ahoi2013]作业

3236: [Ahoi2013]作业

Time Limit: 100 Sec   Memory Limit: 512 MB
Submit: 1009   Solved: 387
[ Submit][ Status][ Discuss]

Description

Input

Output

Sample Input

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

Sample Output

2 2
1 1
3 2
2 1

HINT


N=100000,M=1000000

Source

[ Submit][ Status][ Discuss]

莫队算法+树状数组。。
莫队算法注意控制当前答案区间的计算!!!

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

const int maxn = 1E5 + 10;

int n,m,t[2][maxn],app[maxn],num[maxn],a1[maxn*10],a2[maxn*10];

struct Q{
	int l,r,a,b,pos,x;
	bool operator < (const Q &b) const{
		if (pos < b.pos) return 1;
		if (pos > b.pos) return 0;
		return r < b.r;
	}
}q[maxn*10];

void Add(int x,int y,int z)
{
	for (int j = y; j <= n; j += j&-j)
		t[x][j] += z;
}

int sum(int y,int x)
{
	int ret = 0;
	for (int j = y; j; j -= j&-j)
		ret += t[x][j];
	return ret;
}

int main()
{
	#ifdef YZY
		   freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> n >> m;
	for (int i = 1; i <= n; i++) scanf("%d",&num[i]);
	int p = sqrt(n);
	for (int i = 1; i <= m; i++) {
		int l,r,a,b;
		scanf("%d%d%d%d",&l,&r,&a,&b);
		int pos = l/p;
		q[i] = (Q){l,r,a,b,pos,i};
	}
	
	sort(q+1,q+m+1);
	int L,R;
	L = 1;
	R = 0;
	for (int i = 1; i <= m; i++) {
		if (R < q[i].r) 
			for (int j = R+1; j <= q[i].r; j++) {
				Add(0,num[j],1);
				if (!app[num[j]]) Add(1,num[j],1);
				++app[num[j]];
			}
		if (R > q[i].r) 
			for (int j = R; j > q[i].r; j--) {
				Add(0,num[j],-1);
				--app[num[j]];
				if (!app[num[j]]) Add(1,num[j],-1);
			}
		R = q[i].r;
		
		if (L < q[i].l)
			for (int j = L; j < q[i].l; j++) {
				Add(0,num[j],-1);
				--app[num[j]];
				if (!app[num[j]]) Add(1,num[j],-1);
			}
		if (L > q[i].l) 
			for (int j = L-1; j >= q[i].l; j--) {
				Add(0,num[j],1);
				if (!app[num[j]]) Add(1,num[j],1);
				++app[num[j]];
			}
		L = q[i].l;
		
		a1[q[i].x] = sum(q[i].b,0) - sum(q[i].a-1,0);
		a2[q[i].x] = sum(q[i].b,1) - sum(q[i].a-1,1);
	}
	
	for (int i = 1; i <= m; i++) printf("%d %d\n",a1[i],a2[i]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值