最逆天的一集。

ARC184 A

题目解析

关键观察:注意到 \(m\) 很小,只有 \(10\),并且 \(q = 950\)。考虑有什么性质。

我们发现 \(m\) 很小,我们考虑挖掘性质。

有一个关键观察:如果有大于 \(10\) 个数的类型相等,那么他们一定都是好的。

如果我们知道了 \(20\) 个数中的相对情况,假设有 \(x\) 个数类型相等,其他 \(n - x\) 个数类型相等,这两种数类型不同,由于上面的性质,当 \(x \neq 10\) 时,数量较多的一类必定是好数,数量较少的一类必定是坏数。

按照上面的启发,我们考虑将 \(1000\) 个数进行分组,每组内有 \(20\) 个数。我们计算这 \(20\) 个数的相对情况(这是容易的),然后根据上面的结论,我们就能知道当一组内两种类型数目不相等时它们的好坏之分。

因此,我们只需要考虑 \(x = 10\) 的情况(这种组别显然最多只有一个)。这好办,我们只需要将在这组内的任意一个数和不在这组内的任意一个数比较,这样我们就能区分出哪一种类别是好数。

需要注意一个细节:这样算下来最多的询问次数会到达 \(951\),所以需要轻微的调整来解决这一问题。具体比较简单,可以看代码。

void solve() {
cin >> n >> m >> q;
vector <int> ans;
for (int i = 1; i <= 50; i ++) {
int l = (i - 1) * 20 + 1, pos = 0, cnt0 = 1, cnt1 = 0;
int tar = -1;
for (int j = 2; j <= 20 && (i != 50 || !ans.empty()); j ++) {
cout << "? " << l << ' ' << l + j - 1 << endl;
cin >> col[l + j - 1];
cnt0 += (col[l + j - 1] == 0);
cnt1 += (col[l + j - 1] == 1);
}
if (i == 50 && ans.empty()) {
for (int j = 1; j <= 19; j ++) {
cout << "? " << 1 << ' ' << j + l - 1 << endl;
cin >> col[j + l - 1];
cnt0 += (col[l + j - 1] == 0);
cnt1 += (col[l + j - 1] == 1);
if (col[j + l - 1] == 1) ans.push_back(j + l - 1);
}
if (cnt1 == 9)
ans.push_back(1000);
break;
}
if (cnt0 < cnt1) {
for (int j = 1; j <= 20; j ++)
if (col[l + j - 1] == 0) ans.push_back(l + j - 1);
} else if (cnt0 > cnt1) {
for (int j = 1; j <= 20; j ++)
if (col[l + j - 1] == 1) ans.push_back(l + j - 1);
} else {
pos = (i == 1 ? 1000 : 1);
cout << "? " << l << ' ' << pos << endl;
cin >> tar;
tar ^= 1;
for (int j = 1; j <= 20; j ++)
if (col[l + j - 1] == tar) ans.push_back(l + j - 1);
break;
}
}
cout << "! ";
for (int x : ans) cout << x << ' ';
cout << endl;
}

ARC184 B

ARC184 C

ARC184 D

关键转换:删点不是很好考虑,所以转换成选点。

首先我们考虑选择的点集有多少不同的。我们先对第一维 \(x\) 坐标进行排序,然后容易想到 \(dp\)。

显然,选择的点集中相邻两个点 \((i, i + 1)\) 肯定需要满足 \(y_i > y_{i + 1}\)。据此,可以想到一种比较 naive 的 \(dp\) 方法:设 \(dp_i\) 表示当前考虑了前 \(i\) 个点(选择了 \(i\)),枚举 \(j\),如果 \(y_j > y_i\) 则可以直接转移。

但是上面这个 \(dp\) 有一个显然的漏洞:重复。因为对于一个删除的点集,可能有多个选择的点集能得到它。因此,我们需要在这些结果相同的点集中选择出一种具有代表性且容易计算的方案。

关键观察:我们再加一条限制,选择任意一个没被删除且没被操作的点,操作它之后一定会删除一个其他点。

通过上面这一个限制,我们就有了一个比较明确的 \(dp\) 思路:设 \(dp_i\) 表示当前考虑了前 \(i\) 个点(选择了 \(i\))的方案数,然后每次枚举 \(j\),并且判断这一转移合不合法。

假设现在有一个选择的点集,我们要判断它是否合法。显然,我们设所有没被删除且没被操作的点所在的点集为 \(T\),然后在点集 \(T\) 中遍历每个点 \(i\) 判断 前面是否存在 \(j\) 使得 \(y_j < y_i\) 或者 后面是否存在 \(j\) 使得 \(y_i < y_j\)

但是现在还有一个问题:在 \(dp\) 的转移中如何判断该方案是否合法?

关键观察:我们称相邻两个已操作的点之间所有没被删除的点为一个段。那么,任意两个段之间没有任何关系。即,设左边的点集为 \(S\),右边的段的点集为 \(T\),那么 \(\forall i \in S, j \in T, y_i > y_j\)。

上面这个观察是显然的,但很重要。那么,我们就可以在转移的过程中,只判断当前这一段是否满足要求即可。

void solve() {
n = read();
for (int i = 1; i <= n; i ++)
t[i].x = read(), t[i].y = read();
sort(t + 1, t + n + 1);
t[0] = {0, n + 1}, t[n + 1] = {n + 1, 0};
dp[0] = 1;
for (int i = 1; i <= n + 1; i ++) {
for (int j = 0; j < i; j ++) {
if (t[j].y <= t[i].y) continue;
for (int k = 1; k <= n; k ++)
vis[k] = 0;
bool flg = 1;
long long mn = 2e18, mx = -2e18;
for (int k = j + 1; k < i; k ++) {
if (!(t[j].y > t[k].y && t[k].y > t[i].y))
continue;
vis[k] |= (mn < t[k].y);
mn = min(mn, t[k].y);
}
for (int k = i - 1; k > j; k --) {
if (!(t[j].y > t[k].y && t[k].y > t[i].y))
continue;
vis[k] |= (mx > t[k].y);
mx = max(mx, t[k].y);
}
for (int k = j + 1; k < i; k ++) {
if (!(t[j].y > t[k].y && t[k].y > t[i].y))
continue;
flg &= (vis[k] == 1);
}
if (flg) {
(dp[i] += dp[j]) %= mod;
}
}
}
cout << dp[n + 1];
}

ARC184 随便写点的更多相关文章

  1. Jquery 随便写些知识点

    针对jQuery随便写些觉得还挺实用的一些东西,也没系统的去理一番,只是想到哪写到哪,写的不完全也请多见谅. jQuery和其他javascript库产生$符号冲突了?$符号想必用jQuery的人都不 ...

  2. 随便写一点最近开发遇到的问题和解决方法 大部分关于laravel和php

    laravel里要想对对象进行自己设计的排序(usort()), 得用匿名方法,  原声php就不用 php里面可以随便写html代码,  比如可以把html直接后缀名改成.php, 然后在任何地方& ...

  3. Jquery网页加载进度条(随笔,当然要随便写,当日记动态心情写咯)

    首先先是吐槽时间... 告诉大家一个好消息,就是有个妹子非常仰慕我的前端技术说要包养我 然后有好多羡慕嫉妒恨的童鞋一定要说,少年你太天真了,那一定是HR 然后我表示她不是HR,本宅的春天貌似要到来了. ...

  4. 忙了好一阵,今天随便写篇关于canvas的小东西

    前几天在朋友圈发了几条3D demo视频,其中就有3D空间组成各种图形.如上! 那么这些图形的每个mesh的坐标可不是手动去写,如果你愿意我当然不拦着!所以今天这篇就来介绍如何获得这些图形的坐标数据. ...

  5. 实现一个最简单的VIM文本编辑器(可能有bug,随便写了一个)

    简单的写了一个文本编辑器,功能很简单,但足以把文件IO相关的操作熟悉了,可能功能或者分配的大小还不够完善.请参考参考: #include <stdio.h> #include <co ...

  6. H5取经之路——随便写点儿

    [相对定位] * 1.使用position:relative:设置元素为相对定位的元素: * 2.定位机制: ①相对于自己原来文档流中的的位置定位,当不指定top等定位值时,不会改变元素位置: ②相对 ...

  7. java用POI操作excel——随便写一下,最基础的东西

    前两天部门实施在做一个东西,需要把客户放在Excel中的数据导入到Oracle数据库中,我就想着直接写一个模板,必要的时候改一下实体类应该可以解放实施同事的双手,不过在实际写的过程中,还是碰到很多问题 ...

  8. 今天一天课,随便写点吧/xk

    知道的越多,不知道的也就越多. 最近想学很多很多东西,但是发现没有一个计划,也没有那么多时间精力,都是想到哪学到哪,有的就是学了一半就放下了,又去学新的,感觉需要规划一下学习路线,时间什么的 推荐一个 ...

  9. Vue.js的小例子--随便写的

    1.领导安排明天给同事们科普下vue 2.简单写了两个小例子 3.话不多说直接上代码 <!DOCTYPE html> <html> <head> <meta ...

  10. <随便写>数据库调优的几种方式

    1.创建索引 要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引 在经常需要进行检索的字段上创建索引,比如要按照表字段username进行检索,那么就应该在姓名字段 ...

随机推荐

  1. js技术之“向数组添加元素”

    一.js中对于数组[]的操作很常见 下面记录一下js向数组添加元素的方法 const array=[1,2,3]; console.log('原数组:',array); 效果图 二.用push在数组后 ...

  2. vue3 基础-补充 ref & provide-inject

    本篇主要对一些被以前内容(渲染, 传值) 等忽略的几个常用小技巧进行补充说明啦. v-once 即对某个dom节点生效, 其会限定只会渲染一次, 不论数据是如何的变化, 演示如下: <!DOCT ...

  3. Pandas 清除 Excel 特殊字符

    清除 Excel 特殊字符 主要是为了做一个笔记, 用 遍历 DataFrame 用正则匹配特殊字符并替换. 是上个月初的项目了, 其中有个将 Excel 传入数据库的时候, 发现有特殊字符, 很奇怪 ...

  4. 使用Node.js打造自己的Git版本控制系统

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...

  5. C#程序的内存缓存

    C#程序可以使用IMemoryCache.IMemoryCache是.NET Core中内置的一个轻量级缓存实现,可以用于在内存中缓存数据,以提高应用程序的性能和响应速度.它支持通过键值对的方式缓存数 ...

  6. IDEA配置实体类Serializable快捷键生成serialVersionUID

      创建实体类后,如果需要继承Serializable类并生成随机序列号serialVersionUID,在IDEA中使用Serializable快捷键最为合适,故这里为大家介绍如何配置此快捷键.   ...

  7. REVM移植小记

      之前做过的一些部署移植的工作,基本都是用C++语言写的,在后来我学了一些Rust,并且慢慢熟悉了Rust的工具链,最近也在尝试部署一些Rust的开源项目到OpenEuler RISC-V操作系统上 ...

  8. Linux下安装Flume

    摘要 flume是由cloudera软件公司产出的可分布式日志收集系统,后于2009年被捐赠了apache软件基金会,为hadoop相关组件之一.尤其近几年随着flume的不断被完善以及升级版本的逐一 ...

  9. 如何正确理解IGBT参数

    文档下载链接:https://cnblogs-img.oss-cn-hangzhou.aliyuncs.com/docs/正确理解IGBT模块规格书参数.pdf

  10. Git镜像网站和Git网站提速方法

    最近开始学习使用git,但是因为git是国外的网站,所以基本就是无法访问.如下图: 通过在网上查找资料,我发现了几个访问git的方法. 方法一.通过镜像网站 镜像网站一: https://github ...