CodeForces 1084 F Max Mex
题意:问在树上的所有路中mex值最大是多少。
题解:
用线段树维护值。
区间[L,R]意味着 区间[L,R]的数可不可以合并。
重点就是合并的问题了。
首先合法的区间只有3种:
1. 一个点。
2. 一条从上到下的线段 即 u->v u = lca(u,v)。
3.一条从下到上到下的线段 u -> p -> v p = lca(u,v)
1 和 1 可以直接合并, 合并之后可能成为 2 或者成为3。
1 和 2 合并的时候 可能变成 2 或者 3。 注意的是 1 往上爬的时候可能出现在 2 的中间位置而不是端点位置。
1 和 3 合并的之后 只会变成 3。并且 p 是不会变得,只有 u 和 v 会变。
2 和 2 合并的时候 可能保持2 也可以变成3。
2 和 3 合并的时候 只会保持3, 并且 p 一样不会边,只有u 和 v 会变。 1 3 合并的操作 和 2 3 合并的操作是一样的。
3 和 3 合并的时候 只会保持3, 还是p不会边, u 和 v 会变。
所以 根据前面说的 我们要记录的是 type, u, v, p,ok。
询问的时候,我们先问出[1,x]哪一段是合法的,然后再在右边去询问能不能把右边的并到[1,x]上。
代码:
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod = (int)1e9+;
const int N = 2e5 + ;
int anc[N][];
int v[N], deep[N];
vector<int> vc[N];
void dfs(int o){
for(int x : vc[o]){
deep[x] = deep[o]+;
anc[x][] = o;
for(int i = ; i < ; ++i) anc[x][i] = anc[anc[x][i-]][i-];
dfs(x);
}
}
int lca(int u, int v){
if(deep[u] > deep[v]) swap(u,v);
int k = deep[v] - deep[u];
for(int i = ; i >= ; --i){
if((k>>i)&) v = anc[v][i];
}
if(u == v) return u;
for(int i = ; i >= ; --i){
if(anc[u][i] != anc[v][i])
u = anc[u][i], v = anc[v][i];
}
return anc[u][];
}
int ok[N<<], pre[N<<], type[N<<], low[N<<][];
void Merge(int rt, int ls, int rs){
ok[rt] = ;
if(!ok[ls] || !ok[rs]) return;
if(pre[ls] == low[ls][] && pre[rs] == low[rs][]){
int fp = lca(pre[ls], pre[rs]);
ok[rt] = ; pre[rt] = fp;
if(fp == pre[ls] || fp == pre[rs]){
type[rt] = ;
if(fp == low[ls][]) low[rt][] = low[rs][];
else low[rt][] = low[ls][];
}
else {
type[rt] = ;
low[rt][] = pre[ls]; low[rt][] = pre[rs];
}
return ;
}
if(pre[ls] == low[ls][]) swap(ls, rs);
if(type[ls] == && type[rs] == && pre[rs] == low[rs][]){
int fp = lca(pre[ls], pre[rs]);
int sp = lca(low[ls][], low[rs][]);
pre[rt] = fp;
if(fp == sp){
if(fp == pre[rs]) {
ok[rt] = ; type[rt] = ;
low[rt][] = low[ls][];
}
else {
ok[rt] = ; type[rt] = ;
low[rt][] = low[ls][]; low[rt][] = low[rs][];
}
}
else if((fp == pre[ls] || fp == pre[rs]) && (sp == low[ls][]||sp == low[rs][])){
ok[rt] = ; type[rt] = ;
if(sp == low[ls][]) low[rt][] = low[rs][];
else low[rt][] = low[ls][];
}
return ;
}
if(type[ls] == && type[rs] == ){
int fp = lca(pre[ls], pre[rs]);
int sp = lca(low[ls][], low[rs][]);
pre[rt] = fp;
if(fp == sp){
type[rt] = ; ok[rt] = ;
low[rt][] = low[ls][]; low[rt][] = low[rs][];
}
else if((fp == pre[ls] || fp == pre[rs]) && (sp == low[ls][]||sp == low[rs][])){
ok[rt] = ; type[rt] = ;
if(sp == low[ls][]) low[rt][] = low[rs][];
else low[rt][] = low[ls][];
}
else ok[rt] = ;
return ;
}
if(type[ls] + type[rs] == ){
if(type[ls] == ) swap(ls, rs);
int fp = lca(pre[ls], pre[rs]);
if(fp != pre[rs]) ok[rt] = ;
else {
type[rt] = ; pre[rt] = fp;
int sp = lca(low[ls][], low[rs][]);
if(sp == low[ls][]){
low[rt][] = low[rs][]; low[rt][] = low[rs][];
ok[rt] = ;
return ;
}
if(sp == low[rs][]){
low[rt][] = low[ls][];
low[rt][] = low[rs][]; ok[rt] = ;
return ;
}
sp = lca(low[ls][], low[rs][]);
if(sp == low[ls][]){
low[rt][] = low[rs][]; low[rt][] = low[rs][];
ok[rt] = ;
return ;
}
if(sp == low[rs][]){
low[rt][] = low[rs][]; low[rt][] = low[ls][];
ok[rt] = ;
return ;
}
return ;
}
return ;
}
if(type[ls] + type[rs] == ){
type[rt] = ;
if(pre[ls] == pre[rs]){
pre[rt] = pre[ls];
int sp1 = lca(low[ls][], low[rs][]), sp2 = lca(low[ls][], low[rs][]);
if((sp1 == low[ls][] || sp1 == low[rs][]) && (sp2 == low[ls][] || sp2 == low[rs][])){
ok[rt] = ;
if(sp1 == low[ls][]) low[rt][] = low[rs][];
else low[rt][] = low[ls][];
if(sp2 == low[ls][]) low[rt][] = low[rs][];
else low[rt][] = low[ls][];
return ;
}
sp1 = lca(low[ls][], low[rs][]), sp2 = lca(low[ls][], low[rs][]);
if((sp1 == low[ls][] || sp1 == low[rs][]) && (sp2 == low[ls][] || sp2 == low[rs][])){
ok[rt] = ;
if(sp1 == low[ls][]) low[rt][] = low[rs][];
else low[rt][] = low[ls][];
if(sp2 == low[ls][]) low[rt][] = low[rs][];
else low[rt][] = low[ls][];
return ;
}
}
}
}
void Update(int L, int k, int l, int r, int rt){
if(l == r){
type[rt] = ok[rt] = ;
low[rt][] = pre[rt] = k;
return ;
}
int m = l+r >> ;
if(L <= m) Update(L, k, lson);
else Update(L, k, rson);
Merge(rt, rt<<, rt<<|);
}
void Copy(int aim, int f){
ok[aim] = ok[f]; pre[aim] = pre[f];
low[aim][] = low[f][]; low[aim][] = low[f][];
type[aim] = type[f];
}
int n, u;
int to = (<<)+, b = , ansr;
int Query(int l, int r, int rt){
if(ok[rt]){
if(b == ) {
b = to; ansr = r; Copy(b, rt);
return ;
}
Merge(to+, to, rt);
if(ok[to+]){
Copy(to, to+); ansr = r;
return ;
}
if(l != r){
int m = l+r >> ;
int k = Query(lson);
if(k == ) Query(rson);
}
return ;
}
int m = l+r >> ;
int k = Query(lson);
if(k == ) Query(rson);
return ;
}
int main(){
scanf("%d", &n);
for(int i = ; i <= n; ++i) scanf("%d", &v[i]), v[i] += ;
for(int i = ; i <= n; ++i){
scanf("%d", &u);
vc[u].pb(i);
}
dfs();
for(int i = ; i <= n; ++i)
Update(v[i], i, , n, );
int q, op, l, r;
scanf("%d", &q);
while(q--){
scanf("%d", &op);
if(op == ){
scanf("%d%d", &l, &r); swap(v[l], v[r]);
Update(v[l], l, , n, ); Update(v[r], r, , n, );
}
else {
b = ; Query(,n,);
printf("%d\n", ansr);
}
}
return ;
}
CodeForces 1084 F Max Mex的更多相关文章
- 【Codeforces 1083C】Max Mex(线段树 & LCA)
Description 给定一颗 \(n\) 个顶点的树,顶点 \(i\) 有点权 \(p_i\).其中 \(p_1,p_2,\cdots, p_n\) 为一个 \(0\sim (n-1)\) 的一个 ...
- Codeforces 1083C Max Mex
Description 一棵\(N\)个节点的树, 每个节点上都有 互不相同的 \([0, ~N-1]\) 的数. 定义一条路径上的数的集合为 \(S\), 求一条路径使得 \(Mex(S)\) 最大 ...
- CF 526F Max Mex(倍增求LCA+线段树路径合并)
Max Mex 题目地址:https://codeforces.com/contest/1084/problem/F 然后合并时注意分情况讨论: 参考代码: #include<bits/stdc ...
- CF 1083 C. Max Mex
C. Max Mex https://codeforces.com/contest/1083/problem/C 题意: 一棵$n$个点的树,每个点上有一个数(每个点的上的数互不相同,而且构成一个0~ ...
- Max Mex
Max Mex 无法直接处理 可以二分答案! [0,mid]是否在同一个链上? 可以不修改地做了 修改? 能不能信息合并?可以! 记录包含[l,r]的最短链的两端 可以[0,k][k+1,mid]合并 ...
- CF1083C Max Mex 线段树
题面 CF1083C Max Mex 题解 首先我们考虑,如果一个数x是某条路径上的mex,那么这个数要满足什么条件? 1 ~ x - 1的数都必须出现过. x必须没出现过. 现在我们要最大化x,那么 ...
- Codeforces 959 F. Mahmoud and Ehab and yet another xor task
\(>Codeforces\space959 F. Mahmoud\ and\ Ehab\ and\ yet\ another\ xor\ task<\) 题目大意 : 给出一个长度为 \ ...
- Codeforces 835 F. Roads in the Kingdom
\(>Codeforces\space835 F. Roads in the Kingdom<\) 题目大意 : 给你一棵 \(n\) 个点构成的树基环树,你需要删掉一条环边,使其变成一颗 ...
- Codeforces 731 F. Video Cards(前缀和)
Codeforces 731 F. Video Cards 题目大意:给一组数,从中选一个数作lead,要求其他所有数减少为其倍数,再求和.问所求和的最大值. 思路:统计每个数字出现的个数,再做前缀和 ...
随机推荐
- Cell Phone Networ (树形dp-最小支配集)
目录 Cell Phone Networ (树形dp-最小支配集) 题意 思路 题解 Cell Phone Networ (树形dp-最小支配集) Farmer John has decided to ...
- MOCTF-Crypt-writeup
MOctf Crypt Writeup记录 都不难,就随便记录记录下. MOCTF平台地址:http://www.moctf.com 0x01 数据库密码 hint:20岁的小刚,自幼热爱信息安全,一 ...
- 自定义SWT控件一之自定义单选下拉框
一.自定义下拉控件 自定义的下拉框,是自定义样式的,其中的下拉框使用的是独立的window,非复选框的下拉框双击单机其它区域或选择完之后,独立window构成的下拉框会自动消失. package co ...
- 【Java例题】7.5 文件题2-学生成绩统计
5.学生成绩统计.已有一个学生成绩文件,含有多位学生的各三门课的成绩:读取这个文件中的每位学生的三门课成绩,然后计算均分:最后对这些均分按照大于或小于75分的界限,分别写到另两个文件中. packag ...
- Go中的反射reflect
前面我们在学习到struct结构体的时候,因为结构体中的字段首字母大写,而我们想把json文件映射到该结构体上时,需要在在结构体字段后面加上json标签,表明结构体字段和json字段的映射关系.这其中 ...
- hadoop学习(一)----概念和整体架构
程序员就得不停地学习啊,故步自封不能满足公司的业务发展啊!所以我们要有搞事情的精神.都说现在是大数据的时代,可以我们这些码农还在java的业务世界里面转悠呢.好不容易碰到一个可能会用到大数据技术的场景 ...
- Linux下SVN库迁移
在日常的工作中,可能因为一些服务器硬件损坏等问题,不得不把SVN服务器上的SVN版本库进行迁移,下面讲解一下SVN库迁移方案(采用dump & load方案),在实际操作的时候也非常的简单,有 ...
- 测试自动化:java+selenium3 UI自动化(1) - 环境搭建
1.前言 我大概是在2012年第一次正式接触到自动化测试,那个时候跟随我的团队一起,就当时项目的UI自动化尝试做出了探索. 在我离开那家公司的时候,我们的自动化测试体系仍然难言完美,但是也已经达到了非 ...
- 详解InheritableThreadLocal类的使用与原理
在Java并发编程中,InheritableThreadLocal 与 ThreadLocal 都可以用于线程间通信,不同的是 InheritableThreadLocal 继承了 ThreadLoc ...
- MySQL-下载-安装-配置-多版本共存-设置密码-破解密码
目录 MySQL下载安装与配置 官网下载(后面有镜像仓库下载) 从开源镜像仓库下载(快) 开源镜像仓库站点 MySQL的安装 解压 将MySQL添加至环境变量方便启动 配置MySQL 配置编码 安装M ...