「JOISC 2020 Day2」变色龙之恋 (交互题)(分治)(并查集)

2024-01-30 01:08

本文主要是介绍「JOISC 2020 Day2」变色龙之恋 (交互题)(分治)(并查集),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送门

  • O ( n 2 ) O(n^2) O(n2) 做法:两两查询一次,那么给颜色数为 1 的数对连边,那么一个点可以连出 1 或 3 条边
    对于一条的可以直接确定,对于 3 条的,假设当前位 i i i,它喜欢的为 x x x,喜欢它的为 y y y,颜色相同的为 z z z,那么当且仅当查询 ( i , y , z ) (i,y,z) (i,y,z) 时为 1,如果我们给 ( i , y ) , ( i , z ) (i,y),(i,z) (i,y),(i,z) 打上标记,那么两个颜色相同当且仅当这条边被两次打上标记
  • 利用二分图的性质,对于已知的边,可以把 [ 1 , i ) [1,i) [1,i) 的点分成两个集合,集合内均无边,然后在集合中分治,查询次数 3 log ⁡ n 3\log n 3logn,并且这个可以用并查集维护
    复杂度 O ( n 2 log ⁡ n ) O(n^2\log n) O(n2logn),查询次数 O ( n ( 3 log ⁡ n + 6 ) ) O(n(3\log n+6)) O(n(3logn+6))
#include "chameleon.h"
//#include "grader.cpp"
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
cs int N = 1050;
int fa[N], c[N], id[N], d[N];
vector<int> G[N];
int fnd(int x){ return x==fa[x]?x:fnd(fa[x]); }
int fndc(int x){ return x==fa[x]?0:c[x]^fndc(fa[x]); }
void mrg(int u, int v){int fx=fnd(u), fy=fnd(v);if(d[fx]>d[fy]) swap(fx,fy), swap(v,u); if(fx==fy) return;fa[fx]=fy; d[fy]=max(d[fy],d[fx]+1);c[fx]=fndc(u)^fndc(v)^1;
}
bool work_e(vector<int> S, int l, int r, int u, bool flg=0){if(G[u].size()==3) return false; if(l>r) return false;if(!flg){vector<int> T; T.pb(u);for(int i=l; i<=r; i++) T.pb(S[i]);int c = Query(T); if(c>r-l+1) return false;	}if(l==r){ G[u].pb(S[l]);G[S[l]].pb(u);mrg(u,S[l]); return true;}int mid = (l+r) >> 1;bool t = work_e(S,l,mid,u,false);work_e(S,mid+1,r,u,!t); return true;
}
void Solve(int n){srand(time(0));for(int i=1; i<=n+n; i++) id[i]=i;random_shuffle(id+1,id+n+n+1);for(int i=1; i<=n+n; i++) fa[i]=i, c[i]=0;for(int i=1; i<=n+n; i++){vector<int> A, B;for(int j=1; j<i; j++) if(G[id[j]].size()!=3)fndc(id[j])?B.pb(id[j]):A.pb(id[j]);work_e(A,0,A.size()-1,id[i]);work_e(B,0,B.size()-1,id[i]);}static int mp[N][N], vis[N][N];for(int i=1; i<=n+n; i++) if(G[i].size()==1&&!vis[i][G[i][0]]) vis[i][G[i][0]]=vis[G[i][0]][i]=1, Answer(i,G[i][0]);for(int i=1; i<=n+n; i++) if(G[i].size()>1){assert(G[i].size()==3);for(int u=0; u<3; u++) if(G[G[i][u]].size()==3)for(int v=u+1; v<3; v++) if(G[G[i][v]].size()==3){vector<int> S; S.pb(i), S.pb(G[i][u]), S.pb(G[i][v]);if(Query(S)==1){++mp[i][G[i][u]], ++mp[i][G[i][v]];++mp[G[i][u]][i], ++mp[G[i][v]][i];break;}}}for(int i=1; i<=n+n; i++)for(int j=i+1; j<=n+n; j++)if(mp[i][j]==2) Answer(i,j);
}

这篇关于「JOISC 2020 Day2」变色龙之恋 (交互题)(分治)(并查集)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/658674

相关文章

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 1182 并查集 食物链类

题意: 有n只动物,分别编号1....n。所有动物都属于A,B,C中的一种,已知A吃B,B吃C,C吃A。 按顺序给出下面两种共K条信息: 1. x 和 y 属于同一类。 2. x 吃 y 。 然而这些信息可能会出错,有可能有的信息和之前给出的信息矛盾,也有的信息可能给出的 x 和 y 不在n的范围内。 求k条信息中有多少条是不正确的。 解析: 对于每只动物,创建3个元素 i

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

POJ1988带权并查集

M u v 将u所在的堆移动到v所在的堆的上面 C u 求u的下面有多少块 带权并查集 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;i

POJ1703带权并查集

D: u v  u与v在不同的集合 A: u v  查询u与v的关系 1)压缩路径过程        fu->root   0  1  u-fu 0                 0  1   1                 1  0 2)合并过程 fu->fv      u->fu   0 1   v->fv 0            1 0 1            0

uniapp设置微信小程序的交互反馈

链接:uni.showToast(OBJECT) | uni-app官网 (dcloud.net.cn) 设置操作成功的弹窗: title是我们弹窗提示的文字 showToast是我们在加载的时候进入就会弹出的提示。 2.设置失败的提示窗口和标签 icon:'error'是设置我们失败的logo 设置的文字上限是7个文字,如果需要设置的提示文字过长就需要设置icon并给

Kubernetes 之 kubelet 与 CRI、CNI 的交互过程

序言 当一个新的 Pod 被提交创建之后,Kubelet、CRI、CNI 这三个组件之间进行了哪些交互? Kubelet -> CRI -> CNI 如上图所示: Kubelet 从 kube-api-server 处监听到有新的 pod 被调度到了自己的节点且需要创建。Kubelet 创建 sandbox 并配置好 Pod 的环境,其中包括: Kubelet 通过 gRPC 调用 C

并查集基础与简单扩展应用

并查集 基础题目路径压缩 扩展应用扩展题目1扩展题目2 并查集的结构是一棵树 并查集有两种功能,一种是判断两个元素是否在同一集合,第二种是合并两个集合 并查集的实现需要记录每个节点的父亲节点 判断两个元素是否在同一集合,即判断两个元素的祖宗节点是否是一个节点(祖宗代表整棵树的根节点) 合并两个集合,即将任意一个集合祖宗的爸爸改为另一个集合的祖宗 基础题目 一共有

Java预备知识 - day2

1.IDEA的简单使用与介绍 1.1 IDEA的项目工程介绍 Day2_0904:项目名称 E:\0_code\Day2_0904:表示当前项目所在路径 .idea:idea软件自动生成的文件夹,最好不要动 src:src==sourse→源,我们的源代码就放在这个文件夹之内 Day2_0904.iml:也是自动生成的文件,不要动 External Libraries:外部库 我这

nyoj99(并查集+欧拉路+dfs)

单词拼接 时间限制: 3000 ms  |  内存限制: 65535 KB 难度: 5 描述 给你一些单词,请你判断能否把它们首尾串起来串成一串。 前一个单词的结尾应该与下一个单词的道字母相同。 如 aloha dog arachnid gopher tiger rat   可以拼接成:aloha.arachnid.dog.gopher.rat.tiger 输入 第一行是一个整