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,要求其他所有数减少为其倍数,再求和.问所求和的最大值. 思路:统计每个数字出现的个数,再做前缀和 ...
随机推荐
- Mybatis与Spring集成时都做了什么?
Mybatis是java开发者非常熟悉的ORM框架,Spring集成Mybatis更是我们的日常开发姿势. 本篇主要讲Mybatis与Spring集成所做的事情,让读过本文的开发者对Mybatis和S ...
- codeforces 327 B. Hungry Sequence
题目链接 题目就是让你输出n个数的序列,要保证该序列是递增的,并且第i个数的前面不能保护它的约数,我直接先对前100000的素数打表,然后输出前n个,so easy. //cf 191 B #incl ...
- 2019前端面试系列——JS高频手写代码题
实现 new 方法 /* * 1.创建一个空对象 * 2.链接到原型 * 3.绑定this值 * 4.返回新对象 */ // 第一种实现 function createNew() { let obj ...
- 自定义SWT控件二之自定义多选下拉框
2.自定义下拉多选框 package com.view.control.select; import java.util.ArrayList; import java.util.HashMap; im ...
- 夯实Java基础(八)——代码块
在Java中代码块指的是使用”{}”括起来的代码称为代码块.代码块一共分为4种:局部代码块,静态代码块,同步代码块,构造代码块. 1.局部代码块 局部代码块就是定义在方法体内部的代码块. public ...
- Cannot attach the file “MvcMovie.mdf” as database “aspnet-MvcMovie”
今天在微软开发人员官网上学习asp.net mvc5入门的时候,遇到一个棘手的问题,我是按照教程一步一步操作的,但期间遇到一个自己觉得莫名其妙的问题,教程中也没有提到这个, 在添加新字段这一章节,跟着 ...
- cogs 1254. 最难的任务 Dijkstra + 重边处理
1254. 最难的任务 ★ 输入文件:hardest.in 输出文件:hardest.out 简单对比时间限制:1 s 内存限制:128 MB [题目描述] 这个真的很难.算出 123 ...
- ASP.NET Core 框架本质学习
本文作为学习过程中的一个记录. 学习文章地址: https://www.cnblogs.com/artech/p/inside-asp-net-core-framework.html 一. ASP.N ...
- DT-06 For Homekit
一. 配置DT-06上网 连接此热点,会自动弹出wifi配置页面. 输入选中的路由密码,点 Join加入,如果路由没有出现在列表中,点 Other手工输入(仅支持2.4g路由配置) 二.配置dt-06 ...
- 重读《学习JavaScript数据结构与算法-第三版》- 第3章 数组(一)
定场诗 大将生来胆气豪,腰横秋水雁翎刀. 风吹鼍鼓山河动,电闪旌旗日月高. 天上麒麟原有种,穴中蝼蚁岂能逃. 太平待诏归来日,朕与先生解战袍. 此处应该有掌声... 前言 读<学习JavaScr ...