【LG2154】[SDOI2009]虔诚的墓主人
【LG2154】[SDOI2009]虔诚的墓主人
题面
题解
如果您没有看懂题,请反复阅读题面及样例
可以发现,对于某一个点,它的答案就是上下左右几个组合数乘起来。
这样直接做复杂度显然爆炸,考虑怎么优化这个东西。
我们可以固定左右,在某两个左右之间维护上下有多少个,这样子的话左右的贡献就是不变的,而且你最多只会变化\(O(n)\)次左右边界,复杂度有保证。
这样的话,每次查询一个左右边界内上下的贡献,用线段树维护即可。(描述可能有些模糊,具体详见代码)
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 1e5 + 5;
#define lson (o << 1)
#define rson (o << 1 | 1)
int sum[MAX_N << 2];
void modify(int o, int l, int r, int pos, int v) {
if (l == r) return (void)(sum[o] = v);
int mid = (l + r) >> 1;
if (pos <= mid) modify(lson, l, mid, pos, v);
else modify(rson, mid + 1, r, pos, v);
sum[o] = sum[lson] + sum[rson];
}
int query(int o, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return sum[o];
int mid = (l + r) >> 1, res = 0;
if (ql <= mid) res += query(lson, l, mid, ql, qr);
if (qr > mid) res += query(rson, mid + 1, r, ql, qr);
return res;
}
int W, H, N, K;
int x[MAX_N], y[MAX_N], ox[MAX_N], oy[MAX_N], tx, ty;
vector<int> vec[MAX_N];
int C[MAX_N][15], c1[MAX_N], c2[MAX_N];
bool cmp(const int &l, const int &r) { return y[l] < y[r]; }
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
W = gi(), H = gi(), N = gi();
for (int i = 1; i <= N; i++) x[i] = ox[i] = gi(), y[i] = oy[i] = gi();
K = gi();
sort(&ox[1], &ox[N + 1]), sort(&oy[1], &oy[N + 1]);
tx = unique(&ox[1], &ox[N + 1]) - ox - 1;
ty = unique(&oy[1], &oy[N + 1]) - oy - 1;
for (int i = 1; i <= N; i++) {
x[i] = lower_bound(&ox[1], &ox[tx + 1], x[i]) - ox;
y[i] = lower_bound(&oy[1], &oy[ty + 1], y[i]) - oy;
}
for (int i = 1; i <= N; i++) vec[x[i]].push_back(i), c1[y[i]]++;
for (int i = 1; i <= tx; i++) vec[i].push_back(N + 1);
y[N + 1] = ty + 1;
for (int i = 1; i <= tx; i++) sort(vec[i].begin(), vec[i].end(), cmp);
for (int i = 0; i <= N; i++) C[i][0] = 1;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= min(i, K); j++)
C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
int ans = 0;
for (int i = 1; i <= tx; i++) {
int res = 0, sz = vec[i].size();
for (int j = 0; j < sz; j++) {
int l = j ? y[vec[i][j - 1]] : 0, r = y[vec[i][j]];
if (l + 1 <= r - 1) ans += res * query(1, 1, ty, l + 1, r - 1);
if (j == sz - 1) break;
res = C[j + 1][K] * C[sz - j - 2][K];
++c2[r];
modify(1, 1, ty, r, C[c2[r]][K] * C[c1[r] - c2[r]][K]);
}
}
if (ans < 0) ans += 2147483648ll;
printf("%d\n", ans);
return 0;
}
【LG2154】[SDOI2009]虔诚的墓主人的更多相关文章
- BZOJ 1227: [SDOI2009]虔诚的墓主人
1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec Memory Limit: 259 MBSubmit: 1078 Solved: 510[Submit][Stat ...
- Bzoj 1227: [SDOI2009]虔诚的墓主人 树状数组,离散化,组合数学
1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec Memory Limit: 259 MBSubmit: 895 Solved: 422[Submit][Statu ...
- bzoj1227 [SDOI2009]虔诚的墓主人(组合公式+离散化+线段树)
1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec Memory Limit: 259 MBSubmit: 803 Solved: 372[Submit][Statu ...
- 1227: [SDOI2009]虔诚的墓主人
1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec Memory Limit: 259 MBSubmit: 1083 Solved: 514[Submit][Stat ...
- bzoj1227 P2154 [SDOI2009]虔诚的墓主人
P2154 [SDOI2009]虔诚的墓主人 组合数学+离散化+树状数组 先看题,结合样例分析,易得每个墓地的虔诚度=C(正左几棵,k)*C(正右几棵,k)*C(正上几棵,k)*C(正下几棵,k),如 ...
- 【BZOJ1227】[SDOI2009]虔诚的墓主人(线段树)
[BZOJ1227][SDOI2009]虔诚的墓主人(线段树) 题面 BZOJ 洛谷 题解 显然发现答案就是对于每一个空位置,考虑上下左右各有多少棵树,然后就是这四个方向上树的数量中选\(K\)棵出来 ...
- BZOJ1227 SDOI2009 虔诚的墓主人【树状数组+组合数】【好题】*
BZOJ1227 SDOI2009 虔诚的墓主人 Description 小W 是一片新造公墓的管理人.公墓可以看成一块N×M 的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地. ...
- [BZOJ1227][SDOI2009]虔诚的墓主人 组合数+树状数组
1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec Memory Limit: 259 MBSubmit: 1433 Solved: 672[Submit][Stat ...
- luoguP2154 [SDOI2009]虔诚的墓主人
SDOI2009虔诚的墓主人 喜闻乐见,我终于把此题读懂了..所以可以写了. 其实就是让我们求有多少个十字架 一个十字架的定义为中间有一个空地 周围4个正方向都有k棵树. 不难想到nm的暴力 我们预处 ...
随机推荐
- protoc文件生成cs文件
1.下载protoc工具 点击下载 2.下载解压后打开文件,其中有一个.bat文件,里面对应命令行如下: 编写如下命令行 protoc.exe -I=. --csharp_out=. --grpc_ ...
- Weyland-Energy 说明
Weyland-Energy 说明 品名:Weyland-Energy 大脑能量补充剂功能:提神.提高注意力服用方法:建议饭后1颗,一天1次或者2次,间隔4-6小时,一天不要超过4片. 成分:每2颗含 ...
- 详细的Hadoop的入门教程-伪分布模式Pseudo-Distributed Operation
一. 伪分布模式Pseudo-Distributed Operation 这里关于VM虚拟机的安装就不再介绍了,详细请看<VMware虚拟机的三种网络管理模式>一章介绍.这章只介绍hado ...
- python基础09--闭包,装饰器
1.1 闭包 1.函数作为第一类对象,支持赋值给变量,作为参数传递给其它函数,作为其它函数的返回值,支持函数的嵌套,实现了__call__方法的类实例对象也可以当做函数被调用 2.s= func - ...
- js获取某月有多少天
var day = new Date(2018,10,0); //最后一个参数为0,意为获取2018年10月一共多少天 console.log(day.getDate());
- js学习之面向对象
一.创建对象的方法 1. {} 字面量创建 var person ={ name: "lisi", age: , say: function(){ alert(this.name) ...
- Cheat Engine 特征码
打开游戏 引用自动注入 搜索特征码 特征码,是游戏运行中,唯一的汇编代码 验证,特征码是游戏中唯一代码 添加特征码 添加特征码,以及金钱只增不减代码 进行激活测试 特征码,只有在游戏过程中才会执行到 ...
- mysql-luster没有data目录
mysqld --initialize-insecure --user=mysql 直接复制上面这条命令 然后cmd进入到 mysql解压出来bin的目录中: 等待一会 就发发现data的这个目录了 ...
- PHP公众号开发给用户发微信消息提醒功能
最近做的一个项目,当有用户有资金到账或者成员变动时需要给他发一条微信消息提示.针对这个,开始想使用模板消息,但是刚注册的公众号申请消息模板需要几天时间申请,在时间不足下选择了使用客服消息接口,微信文档 ...
- PHP应用如何对接微信公众号JSAPI支付
微信支付的产品有很多,1. JSAPI支付 2. APP支付 3. Native支付 4.付款码支付 5. H5支付. 其中基于微信公众号开发的应用选择“JSAPI支付“产品,其他APP支付需 ...