loj3161「NOI2019」I 君的探险(随机化,整体二分)

loj

Luogu

题解时间

对于 $ N \le 500 $ 的点,毫无疑问可以直接 $ O(n^2) $ 暴力询问解决。

考虑看起来最好做的 $ B $ 类。

由于有每个点的父亲编号小于该点的优良特性,很容易想到整体二分。

考虑用整体二分求出每个点的父亲:

对于一个分治区间,毫无疑问 $ [l,mid] $ 的节点的父亲在左区间。

而对于另外一半节点,考虑将左半节点全部modify,此时右半某个节点亮起则说明左半节点至少有一个与之相邻,则其父亲在左半区间内。

而对于其他数据,我们依然可以大胆尝试类似的做法,只不过要维护已经确定的边的影响,

并且注意每次将序列随机打乱,同时已经加完边的节点要从序列中删除。

#include<bits/stdc++.h>
// #include"explore.h"
using namespace std;
typedef long long lint;
struct pat{int x,y;pat(int x=0,int y=0):x(x),y(y){}bool operator<(const pat &p)const{return x==p.x?y<p.y:x<p.x;}};
void modify(int x);
int query(int x);
void report(int x,int y);
int check(int x);
const int N=400011;
int n,m;
namespace task500
{
bool check(){return n<=500;}
int tag[N];
void explore()
{
for(int i=0;i<n-1;i++){modify(i);for(int j=i+1;j<n;j++)if(query(j)!=tag[j]) tag[j]^=1,report(i,j);}
}
}
vector<int> ve[N];int tcnt;
namespace taskB
{
bool check(){return n==99997||n==199997;}
void fuck(int l,int r,int px)
{
if(l==r){for(auto x:ve[px])if(x!=l) report(l,x);return;}
int mid=l+r>>1,ls=++tcnt,rs=++tcnt;
for(int i=l;i<=mid;i++) modify(i);
for(auto x:ve[px])
if(x<=mid||query(x)) ve[ls].push_back(x);
else ve[rs].push_back(x);
for(int i=l;i<=mid;i++) modify(i);
fuck(l,mid,ls),fuck(mid+1,r,rs);
}
void explore()
{
tcnt++;for(int i=0;i<n;i++) ve[tcnt].push_back(i);
fuck(0,n-1,tcnt);
}
}
namespace tasknormal
{
int cnt;
int a[N],on[N];
vector<int> to[N];
void report(int x,int y){::report(x,y);to[x].push_back(y),to[y].push_back(x),cnt++;}
int query(int x){int ret=::query(x);for(auto y:to[x]) ret^=on[y];return ret;}
void fuck(int l,int r,int px)
{
if(l==r){for(auto x:ve[px])if(x!=l) report(a[l],a[x]);ve[px].clear();return;}
int mid=l+r>>1,ls=++tcnt,rs=++tcnt;
for(int i=l;i<=mid;i++) modify(a[i]),on[a[i]]=1;
for(auto x:ve[px])
if(x<=mid||query(a[x])) ve[ls].push_back(x);
else ve[rs].push_back(x);
for(int i=l;i<=mid;i++) modify(a[i]),on[a[i]]=0;
fuck(l,mid,ls),fuck(mid+1,r,rs);
ve[px].clear();
}
void explore()
{
for(int i=0;i<n;i++) a[i]=i;
while(cnt<m)
{
random_shuffle(a,a+n);
tcnt=1;for(int i=0;i<n;i++) ve[tcnt].push_back(i);
fuck(0,n-1,tcnt);if(cnt<m)for(int i=0;i<n;i++)if(check(a[i])){swap(a[i],a[n-1]),n--,i--;}
}
}
}
void explore(int n,int m)
{
::n=n,::m=m;
if(task500::check()) task500::explore();
else if(taskB::check()) taskB::explore();
else tasknormal::explore();
}

loj3161「NOI2019」I 君的探险(随机化,整体二分)的更多相关文章

  1. 【LOJ】#2985. 「WC2019」I 君的商店

    LOJ#2985. 「WC2019」I 君的商店 一道很神仙的题啊QAQ 居然是智商题--不是乱搞或者是大数据 我们可以用2N问出一个最大值是1 然后对于任意两个值\(x + y\)和\(a\)比较 ...

  2. loj2985「WC2019」I 君的商店(二分,思维)

    loj2985「WC2019」I 君的商店(二分,思维) loj Luogu 题解时间 真的有点猛的思维题. 首先有一个十分简单的思路: 花费 $ 2N $ 确定一个为 $ 1 $ 的数. 之后每次随 ...

  3. luogu P5473 [NOI2019]I 君的探险 交互 随机 二分 分治 整体二分

    LINK:I 君的探险 神仙题! 考虑一个暴力的做法 每次点亮一个点 询问全部点 这样询问次数为 \(\frac{n\cdot (n-1)}{2}\) 可以通过前5个点. 考虑都为A的部分分 发现一个 ...

  4. LOJ #2985. 「WC2019」I 君的商店

    传送门 搬题解QwQ 首先最大值一定为 \(1\),直接扫一遍两两比较 \(O(2N)\) 求出最大值 设最大值位置为 \(a\),对于任意两个没有确定的位置 \(x,y\) 询问 \([a,x+y] ...

  5. LOJ 3158: 「NOI2019」序列

    题目传送门:LOJ #3158. 题意简述: 给定两个长度为 \(n\) 的正整数序列 \(a,b\),要求在每个序列中都选中 \(K\) 个下标,并且要保证同时在两个序列中都被选中的下标至少有 \( ...

  6. LOJ 3160: 「NOI2019」斗主地

    题目传送门:LOJ #3160. 简要题意: 有一个长度为 \(n\) 的序列 \(a\),初始时 \(a_i=i\) 或 \(a_i=i^2\),这取决于 \(\mathrm{type}\) 的值. ...

  7. LOJ 3159: 「NOI2019」弹跳

    题目传送门:LOJ #3159. 题意简述: 二维平面上有 \(n\) 个整点,给定每个整点的坐标 \((x_i,y_i)\). 有 \(m\) 种边,第 \(i\) 种边从 \(p_i\) 号点连向 ...

  8. LOJ 3156: 「NOI2019」回家路线

    题目传送门:LOJ #3156. 题意简述: 有一张 \(n\) 个点 \(m\) 条边的有向图,边有两个权值 \(p_i\) 和 \(q_i\)(\(p_i<q_i\))表示若 \(p_i\) ...

  9. 「NOI2019」弹跳(KD树)

    题意:w×h网格中有n个点,m条边.每条边可以从p点花费t时间到一个矩形中的任意点,求1号点到每个点的最少时间. \(1<=w,h<=n<=70000,1<=m<=150 ...

随机推荐

  1. Elasticsearch 7.12 启用 x-pack 组件

    文章目录 修改配置文件 设置密码 使用密码 首先,你要有一套es,关于es的部署,可以看我的另一篇博客 ELK-EFK-v7.12.0日志平台部署 $ ./bin/elasticsearch-plug ...

  2. 多端开发之uniapp开发app

    最近在给f做一些工具app,学习了不少关于uniapp编写android应用的知识. 首先,App应用的创建的时候要选择项目类型为uniapp类型.最开始我选择的是h5+项目,这种项目就比较容易写成纯 ...

  3. Lesson1——Tensor

    Tensor Method 描述 is_tensor(obj) 如果 obj 是 PyTorch 张量,则返回 True : is_storage(obj) 如果 obj 是 PyTorch 存储对象 ...

  4. DH密钥交换协议

    密钥交换 密钥交换简单点来说就是允许两名用户在公开媒体上交换信息以生成"一致"的.可以共享的密钥.也就是由甲方产出一对密钥(公钥.私钥),乙方依照甲方公钥产生乙方密钥对(公钥.私钥 ...

  5. 【windows 操作系统】进程间通信(IPC)简述|无名管道和命名管道 消息队列、信号量、共享存储、Socket、Streams等

    一.进程间通信简述 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进 ...

  6. .Net 新一代编译器 Roslyn 会带来怎样的影响?

    .Net 新一代编译器 Roslyn 会带来怎样的影响? Roslyn是微软创建的一个.NET编译器平台,该项目于2014年4月3日开源. 最初 C# 语言的编译器是用 C++ 编写的,后来微软推出了 ...

  7. Spring MVC视图解析器(ViewResolver)

    视图解析器(ViewResolver)是 Spring MVC 的重要组成部分,负责将逻辑视图名解析为具体的视图对象.Spring MVC 提供了很多视图解析类,其中每一项都对应 Java Web 应 ...

  8. python3 使用OpenCV计算滑块拼图验证码缺口位置

    前言 滑块拼图验证码的失败难度在于每次图片上缺口位置不一样,需识别图片上拼图的缺口位置,使用python的OpenCV库来识别到 环境准备 pip 安装 opencv-python pip insta ...

  9. js实现密码输入框对开启键盘大写锁定的提示(IE浏览器下有自动识别提示则不执行(用IE自带效果即可))

    代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...

  10. Spring源码之七registerListeners()及发布订阅模式

    Spring源码之七registerListeners()及发布订阅模式 大家好,我是程序员田同学. 今天带大家解读refresh()方法中的registerListeners()方法,也就是我们经常 ...