牛客小白月赛15 H 数据结构题___分块

题目大意:

一个长度为 n n n的序列 a a a,有 m m m个询问,
每个询问给出 ( l , r , l 1 , r 1 , x ) (l,r,l1,r1,x) (l,r,l1,r1,x)
回答 g e t ( l , r , x ) ∗ g e t ( l 1 , r 1 , x ) get(l,r,x)*get(l1,r1,x) get(l,r,x)get(l1,r1,x) m o d mod mod 20180623 20180623 20180623

g e t ( a , b , c ) get(a,b,c) get(a,b,c)表示区间 [ a , b ] [a,b] [a,b]中有多少个 a i a_i ai满足 a i = c a_i=c ai=c

1 < = n , m < = 1 0 5 ; 1 < = l , r , l 1 , r 1 < = 1 0 5 , a [ i ] ≤ 10000 , x ≤ 100000 1<=n,m<=10^5;1<=l,r,l1,r1<=10^5,a[i]≤10000,x≤100000 1<=n,m<=105;1<=l,r,l1,r1<=105,a[i]10000,x100000
20180623 不 是 质 数 20180623不是质数 20180623

分析:

分块,每个块内都存下这个块内的数,并将其排序,
每次查询就是枚举对应块,首尾直接枚举,中间的各个块二分即可,
时间复杂度: O ( m ∗ n ∗ l o g n ) O(m*\sqrt n*log \sqrt n) O(mn logn )

代码:

#include 

#define N 100005
#define M 1005

using namespace std;

typedef long long ll;

const int mo = 20180623;

struct Node { int l, r, tot; ll c[M]; }d[M];
int n, m, cdp, cnt;
ll a[N];

int Work(int l, int r, ll x)
{
    if (l > r) swap(l, r);
    int sum = 0;
    int posl = l / cdp + (l % cdp ? 1 : 0);
    int posr = r / cdp + (r % cdp ? 1 : 0);
	if (posl == posr)    
    {
    	for (int i = l; i <= r; i++) sum += (a[i] == x ? 1 : 0);
    	return sum;
	}
	for (int i = l; i <= d[posl].r; i++) sum += (a[i] == x ? 1 : 0);
	for (int i = d[posr].l; i <= r; i++) sum += (a[i] == x ? 1 : 0);
	for (int i = posl + 1; i <= posr - 1; i++)
	{
		int ll = lower_bound(d[i].c + 1, d[i].c + d[i].tot + 1, x) - d[i].c;
		int rr = upper_bound(d[i].c + 1, d[i].c + d[i].tot + 1, x) - d[i].c - 1;
		if (d[i].c[ll] == x  && d[i].c[rr] == x) sum += (rr - ll + 1);  
	}
    return sum;
}

int main()
{
	scanf("%d %d", &n, &m);
	cdp = sqrt(n), cnt = 1, d[1].l = 1;
	for (int i = 1; i <= n; i++) 
	{
	    scanf("%lld", &a[i]);
		d[cnt].c[++d[cnt].tot] = a[i];
	    if (i == cdp * cnt) d[cnt++].r = i, d[cnt].l = i + 1; 
    }
    d[cnt].r = n; 
    for (int i = 1; i <= cnt; i++) sort(d[i].c + 1, d[i].c + d[i].tot + 1);
	int l1, r1, l2, r2; ll num;
	for (int i = 1; i <= m; i++)
	{
		scanf("%d %d %d %d %lld", &l1, &r1, &l2, &r2, &num);
		int num1 = Work(l1, r1, num);
		int num2 = Work(l2, r2, num);
		int ans = (ll)num1 * num2 % mo;
		printf("%d\n%d\n%d\n", num1, num2, ans);
	} 
	return 0;
}

你可能感兴趣的:(C++,分治)