【HDU5213 BestCoder Round 39D】【莫队算法+容斥】Lucky 两个区间各选一个数使得和为K的方案数

原创 2015年11月19日 18:33:41
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=3e4+10,M=12e4+10,Z=1e9+7,ms63=1061109567;
int casenum,casei;
int n,m,K,g;
int l1,r1,l2,r2;
struct A
{
	int o,v,id,l,r;
	A(){}
	A(int o_,int v_,int id_,int l_,int r_){o=o_;v=v_;id=id_;l=l_;r=r_;}
	bool operator < (const A& b)const
	{
		if(id!=b.id)return id<b.id;
		return r<b.r;
	}
}a[M];
int v[N];
int num[N];
int ans[N];
inline int ins(int p)
{
	if(v[p]<K)
	{
		++num[v[p]];
		return num[K-v[p]];
	}
	else return 0;
}
inline int del(int p)
{
	if(v[p]<K)
	{
		--num[v[p]];
		return num[K-v[p]];
	}
	else return 0;
}
int main()
{
	while(~scanf("%d%d",&n,&K))
	{
		int len=sqrt(n);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&v[i]);
			num[i]=0;
		}
		scanf("%d",&m);
		g=0;for(int i=1;i<=m;i++)
		{
			scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
			a[i].id=a[i].l/len;
			a[++g]=A(i,1,l1/len,l1,r2);
			a[++g]=A(i,-1,l1/len,l1,l2-1);
			a[++g]=A(i,-1,(r1+1)/len,r1+1,r2);
			if(r1+1<=l2-1)a[++g]=A(i,1,(r1+1)/len,r1+1,l2-1);
			ans[i]=0;
		}
		sort(a+1,a+g+1);
		int ANS=0;
		int l=a[1].l;
		int r=a[1].l-1;
		for(int i=1;i<=g;i++)
		{
			while(l>a[i].l)ANS+=ins(--l);
			while(r<a[i].r)ANS+=ins(++r);
			while(l<a[i].l)ANS-=del(l++);
			while(r>a[i].r)ANS-=del(r--);
			ans[a[i].o]+=ANS*a[i].v;
		}
		for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
	}
	return 0;
}
/*
【trick&&吐槽】
果然题目难度都只不过是一步步升级而来的呀。
会了莫队之后,只要再学会容斥一下这道题就能做出来了哇!
加油~

【题意】
T(5)组数据
每组数据给你n(1<=n<=30000)个数字,每个数字都在[1,n]之间。
并且有m(1<=m<=30000)个询问。
还告诉你一个数字K(2<=k<=2n且k为奇数)。
对于第i个询问,给你2个区间,
[l1~r1] [l2~r2],数据保证1<=l1<=r1<l2<=r2<=n
让你求出有多少对pair(a[x],a[y]),使得——
a[x]在[l1,r1],a[y]在[l2,r2]且a[x]+a[y]==K.

【类型】
莫队算法

【分析】
这道题设计到区间询问,而且可以离线处理。于是我们很自然地想到莫队算法。
我们发现数字的范围很小,于是我们可以直接计数1~n的数分别是多少个。
然后因为K为奇数,所以就自然不会需要考虑一个数和自己自成pair。

这道题有一个需要处理的问题,就是一般的莫队是只有一个区间,而这道题却有两个区间,该怎么办?
于是我们还需要——容斥。

我们定义符号f(a,b)表示询问区间为a,b下的答案,
其实更准确的意思是,在这个区间选择两个为a[i],a[j],且i<j的,且a[i]+a[j]==K的方案数
并且用+表示集合的并。
对于f(a,a),我们可以用莫队算法很容易地求得。
我们定义a=(l1,r1),b=(l2,r2),c=(r1+1,l2-1),
(这道题的数据保证了1<=l1<=r1<l2<=r2<=n,于是就不会出现f()内区间的右界小于左界的情况。)
那么f(a,b)则可以拆分成f(a+c+b,a+c+b)-f(a+c,a+c)-f(c+b,c+b)+f(c,c)。
(ps:这个容斥可以通过画一个3*3的矩阵来理解哦~)
于是一个询问就被我们拆成了4部分,套下莫队算法,这道题就可以轻松AC啦!

【时间复杂度&&优化】
O(msqrt(n))

*/

版权声明:题解中哪里写错请一定要指出来QwQ 转载还请注明下出处哦,谢谢^_^

容斥原理专题一

抱歉,很久没有更新博客了。这几天集中刷了容斥原理的题目,于是就来写博客巩固下。容斥原理,我想大家在高中都或多或少的学过。虽然知道原理内容,但是用来解题的话,还是有点小障碍的,特别是不知道怎么写代码。如...
  • shengtao96
  • shengtao96
  • 2016年09月08日 21:33
  • 1178

容斥原理 —— 求1~n有多少个数与k互质(二进制算法详细解释&模板)

这里有一道经典的例题,可以看一下:点击打开链接 这里的n可能要大于k的,所以不能用欧拉函数去做。 我们首先把k分解质因数,储存到p数组中,num表示质因子的数量。 void pr(int k) //...
  • wyg1997
  • wyg1997
  • 2016年07月22日 20:38
  • 1461

容斥原理详解

翻译:vici@cust 对容斥原理的描述 容斥原理是一种重要的组合数学方法,可以让你求解任意大小的集合,或者计算复合事件的概率。 描述        容斥原理可以描述如下:  ...
  • usher_ou
  • usher_ou
  • 2017年03月31日 17:27
  • 742

容斥原理的证明

容斥原理的证明 原链接地址 容斥原理(翻译) - vici - C++博客        我们要证明下面的等式:                  其中B代表全部Ai的集合          ...
  • j_d_m_y
  • j_d_m_y
  • 2015年09月01日 13:07
  • 1395

ACM 容斥原理

VJ 点击打开链接 参考 点击打开链接  非常好的译文:点击打开链接 容斥原理的想法就是求多个集合的并集.所以要先设计好集合. 组合数学问题中,正面解决会困难,常用方法是正难则反,使用容斥原理求反向...
  • gg_gogoing
  • gg_gogoing
  • 2015年02月08日 08:57
  • 3513

容斥原理应用(求1~r中有多少个数与n互素)

容斥原理应用(求1~r中有多少个数与n互素) 分类: 数论2013-08-02 20:15 121人阅读 评论(0) 收藏 举报 问题:求1~r中有多少个数与n互素。 ...
  • pi9nc
  • pi9nc
  • 2013年08月10日 19:29
  • 1481

“容斥原理及其应用”笔记

容斥原理 举例 对{1, 2, … , n}的排列i1, i2, … , in计数,其中1不在第1个位置上(即i1 ≠ 1) 已知1在第一个位置上的排列数和{2, 3, … , n}的排列数(n...
  • ArrowLLL
  • ArrowLLL
  • 2016年08月30日 23:43
  • 835

容斥原理【模板】

容斥原理:在计数时,必须注意无一重复,无一遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计...
  • u011676797
  • u011676797
  • 2015年05月07日 19:49
  • 1187

容斥原理的应用---求1--r中与n互素数的个数

问题:求1~r中有多少个数与n互素。 对于这个问题由容斥原理,我们有3种写法,其实效率差不多。分别是:dfs,队列数组,位运算。 先说说位运算吧: 用二进制1,0来表示第几个素因...
  • acm_lkl
  • acm_lkl
  • 2014年07月26日 21:03
  • 620

三集合容斥原理问题

三集合容斥原理问题
  • Yaroo
  • Yaroo
  • 2016年10月01日 15:30
  • 3557
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【HDU5213 BestCoder Round 39D】【莫队算法+容斥】Lucky 两个区间各选一个数使得和为K的方案数
举报原因:
原因补充:

(最多只允许输入30个字)