【bzoj5016】[Snoi2017]一个简单的询问

5016: [Snoi2017]一个简单的询问

Time Limit: 30 Sec   Memory Limit: 512 MB
Submit: 326   Solved: 221
[ Submit][ Status][ Discuss]

Description

给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出
get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次。

Input

第一行,一个数字N,表示序列长度。
第二行,N个数字,表示a1~aN
第三行,一个数字Q,表示询问个数。
第4~Q+3行,每行四个数字l1,r1,l2,r2,表示询问。
N,Q≤50000
N1≤ai≤N
1≤l1≤r1≤N
1≤l2≤r2≤N
注意:答案有可能超过int的最大值

Output

对于每组询问,输出一行一个数字,表示答案

Sample Input

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

Sample Output

4
1

HINT

Source

[ Submit][ Status][ Discuss]



莫队


设答案为ans(l1,r1,l2,r2)

那么化简一下可以发现

ans(l1,r1,l2,r2) = ans(1,r1,1,r2) - ans(1,l1 - 1,1,r2) - ans(1,r1,1,l2 - 1) + (1,l1 - 1,1,l2 - 1)

差不多就是这样子

然后四个部分明显可以分开来莫队,最后把答案合起来就好了


代码:
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;

typedef long long LL;

const int INF = 2147483647;
const int maxn = 200010;

struct data{
	int id,l,r,be,f;
}q[maxn];

int n,m,len,tot,a[maxn];
int cnt[maxn][2];
LL now,ans[maxn];

inline LL getint()
{
    LL ret = 0,f = 1;
    char c = getchar();
    while (c < '0' || c > '9') 
    {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9')
        ret = ret * 10 + c - '0',c = getchar();
    return ret * f;
}

inline void modify(int l,int r,int d,int f)
{
	for (int i = l; i <= r; i++)
	{
		if (i == 0) continue;
		now += f * cnt[a[i]][d ^ 1];
		cnt[a[i]][d] += f;
	}
}

inline int cmp(data a,data b)
{
	return (a.be < b.be) || (a.be == b.be && a.r < b.r);
}

int main()
{
    #ifdef AMC
        freopen("AMC1.txt","r",stdin);
    #endif
    n = getint();
    for (int i = 1; i <= n; i++)
    	a[i] = getint(); 
    len = sqrt(n);
    m = getint();
    for (int i = 1; i <= m; i++)
    {
    	int l1 = getint(),r1 = getint(),l2 = getint(),r2 = getint();
    	q[++tot] = (data){i,r1,r2,ceil(1.0 * r1 / len),1};
    	q[++tot] = (data){i,r1,l2 - 1,ceil(1.0 * r1 / len),-1};
    	q[++tot] = (data){i,l1 - 1,r2,ceil(1.0 * (l1 - 1) / len),-1};
    	q[++tot] = (data){i,l1 - 1,l2 - 1,ceil(1.0 * (l1 - 1) / len),1};
	}
	sort(q + 1,q + tot + 1,cmp);
	q[0].r = -1;
	for (int i = 1; i <= tot; i++)
	{
		int test;
		if (i == 5)
			test = 1;
		if (q[i - 1].l < q[i].l)
			modify(q[i - 1].l + 1,q[i].l,0,1);
		if (q[i].l < q[i - 1].l)
			modify(q[i].l + 1,q[i - 1].l,0,-1);
			
		if (q[i - 1].r < q[i].r)
			modify(q[i - 1].r + 1,q[i].r,1,1);
		if (q[i].r < q[i - 1].r)
			modify(q[i].r + 1,q[i - 1].r,1,-1);
		ans[q[i].id] += q[i].f * now;
	}
	for (int i = 1; i <= m; i++)
		printf("%lld\n",ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/joky_2002/article/details/80708864