hdu 5213

来源:互联网 发布:linux源码编译mysql 编辑:程序博客网 时间:2024/06/03 14:22

问题描述

wldn个数(a1...an)

保证对于任意$1 \leq i \leq n1 \leq ai \leq n$

wld有一个常数k保证2 \leq k\leq 2*n2≤k≤2n

为了消除歧义保证k为奇数

他有mm个询问

每个询问有参数l1,r1,l2,r2l1,r1,l2,r2

保证(1 \leq l1\leq r1 < l2 \leq r2 \leq n)(1≤l1≤r1<l2≤r2≤n)

对于每个询问你需要回答有多少个二元组$(ij)$满足:

l1 \leq i\leq r1l1≤ir1l2 \leq j \leq r2l2≤jr2ai + aj = kai+aj=k

保证1 \leq n\leq 30000, 1 \leq m \leq 300001≤n≤30000,1≤m≤30000

输入描述

多组数据(最多55)

对于每组数据:

第一行:一个数nn表示数的个数

接下来一行:一个数kk表示wld的常数

接下来一行:nn个数,依次为$a1, a2, … an$

接下来一行:一个数mm表示询问数

接下来mm行:四个数l1, r1, l2, r2l1,r1,l2,r2表示这组询问的参数

输出描述

对于每组数据:

对于每个询问输出二元组的数目

输入样例

5

3

1 2 1 2 3

1

1 2 3 5

输出样例

2

Hint

a1 + a4 = 3

a2 + a3 = 3

思路:序列莫队加上容斥定理

设f(x,y)为区间[x,y]满足a[x]+a[y]=k的个数,则f(l1,r1,l2,r2)=f(l1,r2)-f(r1+1,r2)-f(l1,l2-1)+f(r1+1,l2-1);

代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 30005;const int blocksize = 200;struct node{int left, right, id, p;void init(int l1, int r1, int id1, int p1){left = l1, right = r1;id = id1, p = p1;}}query[4 * maxn];bool cmp(node &a, node &b){if (a.left / blocksize != b.left / blocksize) return a.left / blocksize < b.left / blocksize;return  a.right < b.right;}int cnt[2 * maxn], a[maxn], ans[maxn], n, k;int main(){while (scanf("%d", &n) != EOF){int cnt1 = 0;scanf("%d", &k);for (int i = 1;i <= n;i++)scanf("%d", &a[i]);memset(cnt, 0, sizeof(cnt));memset(ans, 0, sizeof(ans));int q;scanf("%d", &q);for (int i = 1;i <= q;i++){int l1, r1, l2, r2;scanf("%d%d%d%d", &l1, &r1, &l2, &r2);query[cnt1++].init(l1, r2, i, 1);query[cnt1++].init(r1 + 1, r2, i, -1);query[cnt1++].init(l1, l2 - 1, i, -1);if (r1 + 1 <= l2 - 1) query[cnt1++].init(r1 + 1, l2 - 1, i, 1);}sort(query, query + cnt1, cmp);int left = 1, right = 0, res = 0;for (int i = 0;i < cnt1;i++){while (left > query[i].left){left--;if (k > a[left] && k - a[left] <= n)res += cnt[k - a[left]];cnt[a[left]]++;}while (right < query[i].right){right++;if (k > a[right] && k - a[right] <= n)res += cnt[k - a[right]];cnt[a[right]]++;}while (left < query[i].left){cnt[a[left]]--;if (k > a[left] && k - a[left] <= n)res -= cnt[k - a[left]];left++;}while (right > query[i].right){cnt[a[right]]--;if (k > a[right] && k - a[right] <= n)res -= cnt[k - a[right]];right--;}ans[query[i].id] += res*query[i].p;}for (int i = 1;i <= q;i++)printf("%d\n", ans[i]);}return 0;}



0 0
原创粉丝点击