题目

Codeforces627E

翻译

好久没做英语阅读了,来爽一爽吧 ~

描述

保罗是管弦乐队的成员。弦乐组安排在一个 \(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(双指针_链表)的更多相关文章

  1. BZOJ_1713_[Usaco2007 China]The Bovine Accordion and Banjo Orchestra 音乐会_斜率优化

    BZOJ_1713_[Usaco2007 China]The Bovine Accordion and Banjo Orchestra 音乐会_斜率优化 Description Input 第1行输入 ...

  2. 【Warrior刷题笔记】143.重排链表 【线性化 || 双指针+翻转链表+链表合并】详细注释

    题目一 力扣143.重排链表 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/reorder-list/ 1.描述 给定一个单链表L的头节点he ...

  3. 《LeetBook》leetcode题解(19):Remove Nth Node From End of List[E]——双指针解决链表倒数问题

    我现在在做一个叫<leetbook>的开源书项目,把解题思路都同步更新到github上了,需要的同学可以去看看 这个是书的地址: https://hk029.gitbooks.io/lee ...

  4. (转)c语言_链表实例讲解(两个经典例子)

    建立一个学生成绩的线性链表,对其实现插入,删除,输出,最后销毁. #include <stdio.h>#include <stdlib.h> struct grade {    ...

  5. C_数据结构_链表的链式实现

    传统的链表不能实现数据和链表的分离,一旦数据改变则链表就不能用了,就要重新开发. 如上说示:外层是Teacher,里面小的是node. #ifndef _MYLINKLIST_H_ #define _ ...

  6. c语言_链表实例讲解(两个经典例子)

    建立一个学生成绩的线性链表,对其实现插入,删除,输出,最后销毁. demo1 // lianbiao.cpp : Defines the entry point for the console app ...

  7. 指针与数据结构算法_链表(C语言)

    一.变量: 声明一个变量系统是没有给这个变量分配内存空间的: 例: int j;//编译的时候是没有分配内存空间的 ;//计算机在编译的时候就会给这个i分配4个字节的内存空间 二.malloc动态分配 ...

  8. c_数据结构_链表

    #include<stdio.h> #include<stdlib.h> #define ERROR 0 #define OK 1 #define OVERFLOW -2 ty ...

  9. [数据结构]_[C/C++]_[链表的最佳创建方式]

    场景 1.链表在C/C++里使用非常频繁, 因为它非常使用, 可作为天然的可变数组. push到末尾时对前面的链表项不影响. 反观C数组和std::vector, 一个是静态大小, 一个是增加多了会对 ...

随机推荐

  1. python - 全局中间件(2.7)

    一.场景 在网站的所有页面中可能某些地方都需要相同的数据,此时可以在Django中定义全局数据并存储在session中,或使用模板语言放入页面中 注意:一定要加上 try: 进行潜在的异常捕捉,因为一 ...

  2. Arduino OV7670 live image over USB to PC

    https://www.youtube.com/watch?v=L9DTW1ulsT0 https://www.youtube.com/watch?v=Dp3RMb0e1eA

  3. Ansible自动部署lnmp架构+上线电商

    1.首先准备3台机器 ansible机器:192.168.52.34 目标主机:192.168.52.35 目标主机:192.168.52.36 2.关闭防火墙 [root@localhost ~]# ...

  4. luogu_2605: 基站选址

    洛谷2605:基站选址 题意描述: 有\(N\)个村庄在一条直线上,第\(i(i>1)\)个村庄的距离第\(1\)个村庄的距离为\(D_i\). 需要在这些村庄中建立不超过\(K\)个通讯站,在 ...

  5. Python 11 提取括号中间的内容

    原文:https://blog.csdn.net/your_answer/article/details/80456550 import re string = 'abe(ac)ad)' p1 = r ...

  6. MyBatis智能标签!

    if 语句 <select id="getOne" resultType="com.mybatis.entity.SmbmsProviderEntity" ...

  7. utility.py:61: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array in

    utility.py:: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; ...

  8. 【CSP膜你赛】柠檬的密码(manacher 二分 单调性 st表)

    题目描述 Lemon觉得他需要一个复杂的密码来保证他的帐号的安全.他经过多日思考,决定使用一个长度为奇数的回文串来作为他的密码.  但是这个回文串太长了,Lemon记不住,于是Lemon决定把它记在本 ...

  9. SpringBoot之文件上传体积过大问题(解决方案)

    错误信息如下(关键): org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the re ...

  10. Guava Cache 缓存实现与源码分析

    目录 一.概述 1.内存缓存 2.核心数据结构 二.具体实现 0.一览众山小 1.CacheBuilder 构建器 2.LocalCache 一.概述 1.内存缓存 可看作一个jdk7的concurr ...