「题解报告」P2154 虔诚的墓主人
P2154 虔诚的墓主人 题解
题意
在 \(n\times m\) 一个方格上给你 \(w\) 个点,求方格里每个点正上下左右各选 \(k\) 个点的方案数。
\(1 \le N, M \le 1,000,000,000,0 \le x_i \le N,0 \le y_i \le M,1 \le W \le 100,000,1 \le k \le 10\)。
思路
首先看到 \(N,M\) 这么大,肯定要先离散化一下。
然后考虑怎么求方案数。
我们先对离散化后的点排个序,然后考虑两个 \(x\) 相同的点 \(x,y1\) 和 \(x,y2\) 之间的所有点的方案数。
显然是:
\]
你们意会一下。
观察这个式子,\(C_{y1\_UP}^{k}\times C_{y2\_DOWN}^{k}\) 当前已知,可以用前缀和维护 \(\sum C_{l\_LEFT}^{k}\times C_{l\_RIGHT}^{k}\)。
那么我们就开一个树状数组,维护前 \(i\) 行的 \(C_{l\_LEFT}^{k}\times C_{l\_RIGHT}^{k}\) 之和,每次碰到一个点 \(x,yy\) 时把当前行的影响清除,再令 \(yy\_LEFT+1,yy\_RIGHT-1\),再重新计入前缀和。
可以参考代码中 Solve 函数中变量 \(u\) 的求法。
时间复杂度 \(O(nlogn)\)。
我这个菜鸡居然因为取模取错了调了两节课。
Code
#include <bits/stdc++.h>
#define _for(i,a,b) for(ll i=a;i<=b;++i)
#define for_(i,a,b) for(ll i=a;i>=b;--i)
#define ll long long
using namespace std;
const ll N=1e5+10,P=2147483648;
ll n,m,w,k,q[N],h[N],z[N],y[N],ans;
struct tree{ll x,y;}t[N];
inline ll rnt(){
	ll x=0,w=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x*w;
}
namespace SZSZ{
	/*树状数组*/
	ll b[N];
	inline ll lowbit(ll x){return x&-x;}
	inline void UpDate(ll x,ll y){
		while(x<=w){
			b[x]=(b[x]+y)%P;
			x+=lowbit(x);
		}
		return;
	}
	inline ll Query(ll x){
        if(x==0)return 0;
		ll sum=0;
		while(x){
			sum=(sum+b[x])%P;
			x-=lowbit(x);
		}
		return sum;
	}
}
namespace LISAN{
	/*离散化*/
	vector<ll>xx,yy;
	inline bool cmp(tree a,tree b){
		if(a.x==b.x)return a.y<b.y;
		return a.x<b.x;
	}
	inline void Add(ll x,ll y){
		xx.push_back(x);
		yy.push_back(y);
		return;
	}
	inline void LiSan(){
		sort(xx.begin(),xx.end());
		sort(yy.begin(),yy.end());
		xx.erase(unique(xx.begin(),xx.end()),xx.end());
		yy.erase(unique(yy.begin(),yy.end()),yy.end());
		_for(i,1,w){
			t[i].x=lower_bound(xx.begin(),xx.end(),t[i].x)-xx.begin()+1;
			t[i].y=lower_bound(yy.begin(),yy.end(),t[i].y)-yy.begin()+1;
			++h[t[i].x],++y[t[i].y];
		}
		sort(t+1,t+w+1,cmp);
		return;
	}
}
namespace SOLVE{
	ll c[N*20][20]={0};
	/*预处理组合数*/
	inline void PreC(){
		c[0][0]=1;
		_for(i,1,w){
			c[i][0]=1;
			_for(j,1,min(k,i))
				c[i][j]=(c[i-1][j]+c[i-1][j-1])%P;
		}
	}
	/*求解*/
	inline ll Solve(){
		PreC();
		_for(i,1,w-1){
			++q[t[i].x];
			++z[t[i].y];
			if(t[i].x==t[i+1].x&&q[t[i].x]>=k&&h[t[i].x]-q[t[i].x]>=k){
				ll up=c[q[t[i].x]][k];
				ll dn=c[h[t[i].x]-q[t[i].x]][k];
				ll ri=SZSZ::Query(t[i+1].y-1)-SZSZ::Query(t[i].y);
				ans+=((up*dn+P)%P*ri+P)%P;
                ans%=P;
			}
			ll u=((c[z[t[i].y]][k]*c[y[t[i].y]-z[t[i].y]][k]+P)%P-(SZSZ::Query(t[i].y)-SZSZ::Query(t[i].y-1)+P)%P+P)%P;
			SZSZ::UpDate(t[i].y,u);
		}
		return ans;
	}
}
int main(){
	n=rnt(),m=rnt(),w=rnt();
	_for(i,1,w){
		t[i].x=rnt(),t[i].y=rnt();
		LISAN::Add(t[i].x,t[i].y);
	}
	k=rnt();
	LISAN::LiSan();
	printf("%lld\n",SOLVE::Solve());
	return 0;
}
/*
*/
												
											「题解报告」P2154 虔诚的墓主人的更多相关文章
- 「题解报告」 P3167 [CQOI2014]通配符匹配
		
「题解报告」 P3167 [CQOI2014]通配符匹配 思路 *和?显然无法直接匹配,但是可以发现「通配符个数不超过 \(10\) 」,那么我们可以考虑分段匹配. 我们首先把原字符串分成多个以一个通 ...
 - 「题解报告」P4577 [FJOI2018]领导集团问题
		
题解 P4577 [FJOI2018]领导集团问题 题解区好像没有线段树上又套了二分的做法,于是就有了这片题解. 题目传送门 怀着必 WA 的决心交了两发,一不小心就过了. 题意 求一个树上最长不下降 ...
 - 「题解报告」SP16185 Mining your own business
		
题解 SP16185 Mining your own business 原题传送门 题意 给你一个无向图,求至少安装多少个太平井,才能使不管那个点封闭,其他点都可以与有太平井的点联通. 题解 其他题解 ...
 - 「题解报告」Blocks
		
P3503 Blocks 题解 原题传送门 思路 首先我们可以发现,若 \(a_l\) ~ \(a_r\) 的平均值大于等于 \(k\) ,则这个区间一定可以转化为都大于等于 \(k\) 的.我们就把 ...
 - 「题解报告」P3354
		
P3354 题解 题目传送门 一道很恶心的树形dp 但是我喜欢 题目大意: 一片海旁边有一条树状的河,入海口有一个大伐木场,每条河的分叉处都有村庄.建了伐木场的村庄可以直接处理木料,否则要往下游的伐木 ...
 - 「题解报告」CF1067A Array Without Local Maximums
		
大佬们的题解都太深奥了,直接把转移方程放出来让其他大佬们感性理解,蒟蒻们很难理解,所以我就写了一篇让像我一样的蒟蒻能看懂的题解 原题传送门 动态规划三部曲:确定状态,转移方程,初始状态和答案. --神 ...
 - 「题解报告」P7301 【[USACO21JAN] Spaced Out S】
		
原题传送门 神奇的5分算法:直接输出样例. 20分算法 直接把每个点是否有牛的状态DFS一遍同时判断是否合法,时间复杂度约为\(O(2^{n^2})\)(因为有判断合法的剪枝所以会比这个低).而在前四 ...
 - 【Luogu】P2154虔诚的墓主人(树状数组)
		
题目链接 这题就是考虑我们有这样一个情况
 - bzoj1227 P2154 [SDOI2009]虔诚的墓主人
		
P2154 [SDOI2009]虔诚的墓主人 组合数学+离散化+树状数组 先看题,结合样例分析,易得每个墓地的虔诚度=C(正左几棵,k)*C(正右几棵,k)*C(正上几棵,k)*C(正下几棵,k),如 ...
 
随机推荐
- Java常用类-包装类
			
包装类  Java中的基本类型功能简单,不具备对象的特性,为了使基本类型具备对象的特性,所以出现了包装类,就可以像操作对象一样操作基本类型数据;包装类不是为了取代基本数据类型,而是在数据类型需要使用 ...
 - 全新升级的AOP框架Dora.Interception[3]: 基于特性标注的拦截器注册方式
			
在Dora.Interception(github地址,觉得不错不妨给一颗星)中按照约定方式定义的拦截器可以采用多种方式注册到目标方法上.本篇文章介绍最常用的基于"特性标注"的拦截 ...
 - Elasticsearch学习系列三(搜索案例实战)
			
Query DSL Es提供了基于JSON的完整查询DSL(Domain Specific Language 特定域的语言)来定义查询.将查询DSL视为查询的AST(抽象语法树).它由两种子句组成: ...
 - python基础知识-day9(数据驱动)
			
1.数据驱动的概念 在自动化测试中,需要把测试的数据分离到JSON,YAML等文件中. 2.YAML 的相关知识 YAML 入门教程 分类 编程技术 YAML 是 "YAML Ain't a ...
 - kubectl 最新常用命令  --V1.24版本
			
Kubectl 自动补全 BASH source <(kubectl completion bash) # 在 bash 中设置当前 shell 的自动补全,要先安装 bash-completi ...
 - P1087 FBI树 [2004普及]
			
这是个正常的.很简单的分治,然后我成功地将这个题搞成了一个贼难搞的东西 还是说一下我那个非常麻烦的思路: 1. 建树 2. 后序遍历 然后就在建树的过程中死循环了,然后还一堆毛病 看了一个AC代码,该 ...
 - Java开发学习(十二)----基于注解开发依赖注入
			
Spring为了使用注解简化开发,并没有提供构造函数注入.setter注入对应的注解,只提供了自动装配的注解实现. 1.环境准备 首先准备环境: 创建一个Maven项目 pom.xml添加Spring ...
 - Solution -「Luogu 5170」类欧几里得算法
			
推柿子大赛了属于是. 题目要求三个柿子,不妨分别记为: \[\begin {align} f (a, b, c, n) &= \sum \limits _{i = 0} ^{n} \lfloo ...
 - day02_基本语法
			
基本语法 学习目标: 1. 数据类型 2. 变量 3. 编码介绍 4. 标识符和关键字 5. 字符串类型 6. 数据类型转化 7. 进制转换 8. 运算符 一.数据类型 什么是数据类型? 在开发软件的 ...
 - Sentry的安装、配置、使用
			
前言 上一篇文章介绍了ExceptionLess这个日志收集系统:ExceptionLess的安装.配置.使用 由于ExceptionLess官方提供的客户端只有.Net/.NetCore平台和js的 ...