Lucky HDU - 5213 (莫队,容斥)
Posted qieqiemin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lucky HDU - 5213 (莫队,容斥)相关的知识,希望对你有一定的参考价值。
WLD is always very lucky.His secret is a lucky number . is a fixed odd number. Now he meets a stranger with numbers:.The stranger asks him questions.Each question is like this:Given two ranges and ,you can choose two numbers and to make .The you can choose is between and and the you can choose is between and .How many pairs of numbers you can choose?
If WLD can answer all the questions correctly,he‘ll be the luckiest man in the world.Can you help him?
Input
There are multiple cases.(At MOST )
For each case:
The first line contains an integer .
The following line contains an integer ,WLD‘s lucky number.K is odd.
The following line contains integers .
The following line contains an integer ,the sum of the questions WLD has to answer.
The following lines,the i-th line contains numbers ,describing the i-th question the stranger asks.
Output
For each case:
Print the total of pairs WLD can choose for each question.
Sample Input
5
3
1 2 1 2 3
1
1 2 3 5
Sample Output
2
Hint
a1+a4=a2+a3=3=K.
So we have two pairs of numbers (1,4) and (2,3).
Good luck!
题意:
给你一个长度为n的数组a,以及一个整数k,和m个询问。
每一个询问给你两个区间分别是 l~r,u~v,
问你有多少对 x,y 满足 a[x]+a[y]=k 并且 l<=x<=r, u<=y<=v
思路:
由于题目的数据范围和支持离线做法,我们容易想到莫队算法
但是我们知道莫队算法只可以处理一个连续的区间问题,不能处理两段连续的区间。
那么我们来考虑能否将两段区间转化为一个连续区间的问题。
我们设F(i,j ) 为 在区间i~j中,x,y (x!=y)满足 a[x]+a[y]=k 的个数。
那么根据容斥定律,我们可以知道。、
F(l1,r1)+F(l2,r2) = F(l1,r2) - F(l1,l2-1 ) - F(r1+1,r2)+F(r1+1,l2-1)
那么我们就可以把问题转化为莫队经典的区间询问问题了。
我们把每一个询问分成上面等式右边的四个部分,同时对于每一个部分维护它对这个询问的贡献是加还是减。
多组输入,记得初始化即可。
细节见代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) return b ? gcd(b, a % b) : a;
ll lcm(ll a, ll b) return a / gcd(a, b) * b;
ll powmod(ll a, ll b, ll MOD) ll ans = 1; while (b) if (b % 2) ans = ans * a % MOD; a = a * a % MOD; b /= 2; return ans;
inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
ll ans[maxn];
ll Ans = 0ll;
int l = 1;
int r = 0;
struct node
int l, r, id;
int op;
a[maxn];
int pos[maxn];
int n, m;
int len;
bool cmp(node aa, node bb)
if (pos[aa.l] == pos[bb.l])
return aa.r < bb.r;
else
return pos[aa.l] < pos[bb.l];
int col[maxn];
int flag[maxn];
int k;
int cnt = 0;
void add(int x)
if ((k >= col[x]))
Ans += flag[k - col[x]];
flag[col[x]]++;
void del(int x)
flag[col[x]]--;
if((k>=col[x]))
Ans-=flag[k-col[x]];
int main()
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
while(~scanf("%d%d",&n,&k))
len = (int)(sqrt(n));
repd(i, 1, n)
gg(col[i]);
gg(m);
repd(i,1,max(n,m))
ans[i]=0ll;
flag[i]=0ll;
cnt=0;
int l1, l2, r1, r2;
repd(i, 1, m)
pos[i] = i / len;
gg(l1); gg(r1); gg(l2); gg(r2);
a[++cnt].l = l1; a[cnt].r = r2; a[cnt].op = 1;a[cnt].id = i;
a[++cnt].l = l1; a[cnt].r = l2-1; a[cnt].op = -1;a[cnt].id = i;
a[++cnt].l = r1+1; a[cnt].r = r2; a[cnt].op = -1;a[cnt].id = i;
a[++cnt].l = r1+1; a[cnt].r = l2-1; a[cnt].op = 1;a[cnt].id = i;
sort(a + 1, a + 1 + cnt, cmp);
repd(i, 1, cnt)
while (l > a[i].l)
l--;
add(l);
while (r < a[i].r)
r++;
add(r);
while (l < a[i].l)
del(l);
l++;
while (r > a[i].r)
del(r);
r--;
// cout<<a[i].l<<" "<<a[i].r<<" "<<Ans<<" "<<a[i].op<<endl;
ans[a[i].id] += Ans * a[i].op;
repd(i, 1, m)
printf("%lld\n", ans[i]);
return 0;
inline void getInt(int *p)
char ch;
do
ch = getchar();
while (ch == ' ' || ch == '\n');
if (ch == '-')
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9')
*p = *p * 10 - ch + '0';
else
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9')
*p = *p * 10 + ch - '0';
以上是关于Lucky HDU - 5213 (莫队,容斥)的主要内容,如果未能解决你的问题,请参考以下文章