【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, 一个是静态大小, 一个是增加多了会对 ...
随机推荐
- js spread object
What’s is the benefit / drawback of these two alternatives? Using object spread options = {...option ...
- Linux定时任务crontab命令
linux 系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的.另外, 由于用户自己也可以设置计划任务,所以,Li ...
- 利用伪寄存器对MSVC++进行调试的介绍
简介 让我们从我写这篇文章的原因开始.一天,一个同事让我帮他调试他遇到的问题.所以我看着他在输入代码,这时我注意到下面一行: int test = GetLastError(); 他这样做是因为他想知 ...
- plotly-dash 简单使用(一)
plotly-dash 是一个很不错的dashboard 开发平台,基于python 编写,提供了很便捷的dashboard 开发模型 同时扩展上也比较灵活我们可以编写自己的组件. 以下是一个简单的项 ...
- Reconstructing Cloud-Contaminated Multispectral Images With Contextualized Autoencoder Neural Networks(自编码机重建云污染区)
1.逐像元输入输出与邻域输入输出,邻域处理是先flatten,再unflatten 2.用MDL方法(最小描述长度)寻找自编码机最佳隐藏层数 3.多目标优化方法寻找MDL方法的超参数,平衡MDL方法两 ...
- BDD的概念
BDD的概念Behavior-Driven Development (BDD) is a set of software engineering practices designed to help ...
- 【POJ1426】Find The Multiple
本题传送门 本题知识点:深度优先搜索 | 宽度优先搜索 题意很简单,让我们找一个只有1和0组成的十位数是n的倍数的数. 这题一开始吓到我了--因为Output里说输出的长度最长不超过100位???那是 ...
- sourceforge文件下载过慢
sourceforge文件下载过慢,可以用下面网址镜像下载, http://sourceforge.mirrorservice.org 按搜索到的项目的英文字母依次查询,如http://sourcef ...
- 从工厂流水线小妹到Google上班程序媛,看完后,我跪服了!
阅读本文大概需要 10.2 分钟. 文作者:Ling Sun 原文链接:https://www.zhihu.com/question/68154951/answer/546265013 我家境很不好, ...
- 有关于服务端模板注入(ssti攻击)——BUUCTF - easy_tornado
打开题目出现3个链接 /flag.txt 中提示flag in /fllllllllllllag /welcome.txt 中提示 render /hints.txt 中提示 md5(cookie_s ...