【Codeforces627E】Orchestra(双指针_链表)
题目
翻译
好久没做英语阅读了,来爽一爽吧 ~
描述
保罗是管弦乐队的成员。弦乐组安排在一个 \(r\times c\) 的矩形方格区域中,其中有 \(n\) 个中提琴手 (violist) ,其余都是小提琴手 (violinist) 。保罗很喜欢中提琴 (viola) ,因此他想拍一张至少包含 \(k\) 个中提琴的照片。保罗可以为管弦乐队中任意一个与坐标轴平行的矩形区域拍照。求出保罗可以拍出的照片的数量。
两张照片不同当且仅当对应的矩形的坐标不同。
输入
第一行输入四个空格隔开的整数 \(r,c,n,k(1\leq r,c,n \leq 3000,1\leq k\leq \min(n,10)\) —— 依次为弦乐组的长和宽,中提琴手的总数和保罗希望照片里中提琴的最少数量。
接下来 \(n\) 行,每行两个整数 \(x_i\) 和 \(y_i(1\leq x_i\leq r,1\leq y_i\leq c)\) :第 \(i\) 个中提琴的位置。保证输入中每个位置出现最多一次。
输出
输出一个整数 —— 保罗可以拍出的至少包含 \(k\) 个中提琴的照片的数量。
分析
为什么他们都会这道题就我不会啊。难受。
以下方便起见设矩阵为 \(n\times m\) ,中提琴数量为 \(V\) …… 懒得改了
有一个很显然的 \(O(n^2m)\) 的暴力:枚举选取的矩阵的上界和下界 \([t,b](1\leq t\leq b\leq n)\),然后用双指针(又称尺取法)算出此时 \([1,m]\) 中有多少个区间 \([l,r](1\leq l\leq r\leq m)\) 满足以 \((t,l)\) 为左上角、 \((b,r)\) 为右下角的矩形(下称 \([l,r]\) 的「对应矩形」)中有至少 \(k\) 个中提琴。
注意到中提琴最多只有 \(3000\) 个,考虑不枚举每一列,而只枚举中提琴,这样总复杂度(没准)能变成 \(O(n^2+nV)\) 之类的东西 …… ?
如果现在处理的行区间是 \([t,b]\) ,当 \(b\) 变成 \(b-1\) 时,由「合法」(即对应矩形中至少有 \(k\) 个中提琴)变为「不合法」的区间 \([l,r]\) ,一定在 \(b\) 这一行包含了至少一个中提琴。因此,只需要枚举 \(b\) 行的中提琴,然后看它让多少个 \([l,r]\) 不合法了即可。更进一步,枚举这一行中的中提琴,找有多少个区间 \([l,r]\) 包含它且对应矩形的中提琴数 恰好 为 \(k\) ,然后删掉这个中提琴。这样就可以不重不漏地统计到所有由合法变为不合法的区间。
还能注意到 \(k\) 非常小。这说明满足条件的 \(l\) 和当前枚举到的中提琴之间不会超过 \(k\) 个「有效列」(指在 \([t,b]\) 中至少一行存在中提琴的列),对于 \(r\) 亦是如此。那么只需要枚举 \(l\) ,用双指针统计即可。「有效列」可以用链表维护。这样就可以在 \(O(k)\) 时间内统计出有多少个包含某个点的区间对应矩形包含的中提琴数恰好为 \(k\) 。总事件复杂度 \(O(n^2+nm+nVk)\) 。
一些计数的细节详见代码。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
namespace zyt
{
typedef long long ll;
typedef pair<int, int> pii;
const int N = 3e3 + 10;
int L[N], R[N], s[N], n, m, t, k, num[N];
ll ans;
pii arr[N];
vector<int> g[N];
int work()
{
scanf("%d%d%d%d", &n, &m, &t, &k);
for (int i = 0; i < t; i++)
scanf("%d%d", &arr[i].first, &arr[i].second), g[arr[i].first].push_back(arr[i].second);
for (int i = 1; i <= n; i++)
sort(g[i].begin(), g[i].end());
for (int i = 1; i <= n; i++)
{
memset(num, 0, sizeof(int[m + 1]));
for (int j = i; j <= n; j++)
for (vector<int>::iterator it = g[j].begin(); it != g[j].end(); it++)
++num[*it];
int last = 0;
for (int j = 1; j <= m; j++)
if (num[j])
L[j] = last, R[last] = j, last = j;
R[last] = m + 1;
int now = 0;
for (int l = R[0], r = R[0], tmp = 0; r <= m; r = R[r])
{
tmp += num[r];
while (tmp - num[l] >= k)
tmp -= num[l], l = R[l];
if (tmp >= k)
now += (R[r] - r) * l;
}
for (int j = n; j >= i; j--)
{
ans += now;
for (vector<int>::iterator it = g[j].begin(); it != g[j].end(); it++)
{
int l = *it, r = *it, tmp = 0;
while (L[l] && tmp < k)
tmp += num[l = L[l]];
while (r <= m)
{
tmp += num[r];
while (tmp > k)
tmp -= num[l], l = R[l];
if (l > *it)
break;
if (tmp == k)
now -= (R[r] - r) * (l - L[l]);
r = R[r];
}
if (!(--num[*it]))
R[L[*it]] = R[*it], L[R[*it]] = L[*it];
}
}
}
printf("%lld", ans);
return 0;
}
}
int main()
{
return zyt::work();
}
【Codeforces627E】Orchestra(双指针_链表)的更多相关文章
- BZOJ_1713_[Usaco2007 China]The Bovine Accordion and Banjo Orchestra 音乐会_斜率优化
BZOJ_1713_[Usaco2007 China]The Bovine Accordion and Banjo Orchestra 音乐会_斜率优化 Description Input 第1行输入 ...
- 【Warrior刷题笔记】143.重排链表 【线性化 || 双指针+翻转链表+链表合并】详细注释
题目一 力扣143.重排链表 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/reorder-list/ 1.描述 给定一个单链表L的头节点he ...
- 《LeetBook》leetcode题解(19):Remove Nth Node From End of List[E]——双指针解决链表倒数问题
我现在在做一个叫<leetbook>的开源书项目,把解题思路都同步更新到github上了,需要的同学可以去看看 这个是书的地址: https://hk029.gitbooks.io/lee ...
- (转)c语言_链表实例讲解(两个经典例子)
建立一个学生成绩的线性链表,对其实现插入,删除,输出,最后销毁. #include <stdio.h>#include <stdlib.h> struct grade { ...
- C_数据结构_链表的链式实现
传统的链表不能实现数据和链表的分离,一旦数据改变则链表就不能用了,就要重新开发. 如上说示:外层是Teacher,里面小的是node. #ifndef _MYLINKLIST_H_ #define _ ...
- c语言_链表实例讲解(两个经典例子)
建立一个学生成绩的线性链表,对其实现插入,删除,输出,最后销毁. demo1 // lianbiao.cpp : Defines the entry point for the console app ...
- 指针与数据结构算法_链表(C语言)
一.变量: 声明一个变量系统是没有给这个变量分配内存空间的: 例: int j;//编译的时候是没有分配内存空间的 ;//计算机在编译的时候就会给这个i分配4个字节的内存空间 二.malloc动态分配 ...
- c_数据结构_链表
#include<stdio.h> #include<stdlib.h> #define ERROR 0 #define OK 1 #define OVERFLOW -2 ty ...
- [数据结构]_[C/C++]_[链表的最佳创建方式]
场景 1.链表在C/C++里使用非常频繁, 因为它非常使用, 可作为天然的可变数组. push到末尾时对前面的链表项不影响. 反观C数组和std::vector, 一个是静态大小, 一个是增加多了会对 ...
随机推荐
- node.js – 服务器端的客户端证书验证,DEPTH_ZERO_SELF_SIGNED_CERT错误
我正在使用节点0.10.26并尝试建立与客户端验证的https连接. 服务器代码: var https = require('https'); var fs = require('fs'); proc ...
- Gcd HYSBZ - 2818 (莫比乌斯反演)
Gcd \[ Time Limit: 10000 ms\quad Memory Limit: 262144 kB \] 题意 求 \(gcd\left(x,y\right) = p\) 的对数,其中\ ...
- 编译lua固件NodeMcu 8266
https://www.cnblogs.com/yangfengwu/p/10547024.html 因为我现在的Wifi的教程是lua语言编写的,但是有些功能需要自己编译lua固件才可以,这篇文章就 ...
- cogs 997. [東方S2] 射命丸文
二次联通门 : cogs 997. [東方S2] 射命丸文 /* cogs 997. [東方S2] 射命丸文 二维前缀和 枚举每个子矩阵 更新最大值.. 莫名rank1 */ #include < ...
- GoCN每日新闻(2019-11-02)
GoCN每日新闻(2019-11-02) GoCN每日新闻(2019-11-02) 1. Go 1.13.4 and Go 1.12.13 are released https://groups.go ...
- Dice Similarity Coefficent vs. IoU Dice系数和IoU
Dice Similarity Coefficent vs. IoU Several readers emailed regarding the segmentation performance of ...
- Chrome提示:"请停用以开发者模式运行的扩展程序"的解决办法
操作步骤 1.开始 -> 运行 -> 输入gpedit.msc -> 回车确定打开计算机本地组策略编辑器(通过Win + R快捷键可以快速打开运行),如图所示: 2.在打开的本地组策 ...
- Densely semantically aligned person re-identification
Densely semantically aligned person re-identification https://arxiv.org/abs/1812.08967
- mvn命令修改pom打包的版本号
在java项目中打包经常需要修改镜像的版本号.可以使用如下命令 mvn versions: // 如果要打包使用人如下命令,打印详细信息使用 -X mvn clean deploy -e -Dskip ...
- SketchyGAN: Towards Diverse and Realistic Sketch to Image Synthesis - 1 - 论文学习
https://github.com/wchen342/SketchyGAN Abstract 从人体草图中合成逼真的图像是计算机图形学和视觉学中的一个具有挑战性的课题.现有的方法要么需要精确的边缘图 ...