SolutionSolutionSolution

求出后缀数组heightiheighti\text{height}_i后。
问题转化为maxi≠j{mini<k≤j{heighti}+(wi xor wj)}maxi≠j{mini<k≤j{heighti}+(wixorwj)}\text{max}_{i\neq j}\{\text{min}_{i\lt k\le j}\{\text{height}_i\}+(w_i~xor~w_j)\}
从大到小枚举作为最小值的heightiheighti\text{height}_i,相当于要找到左右两边取一个数得到的异或和最大值。
可以启发式合并两边的元素,用trie维护,每次枚举较小列表里的元素在另一边询问就好了。
时间复杂度就O(nlog2n)O(nlog2⁡n)\mathcal{O}(n\log^2{n})了。

#include <bits/stdc++.h>
#define show(x) cerr << #x << " = " << x << endl
using namespace std;
typedef long long ll;
typedef pair<int, int> Pairs;const int K = 18;
const int N = 202020;
const int M = 4040404;inline char get(void) {static char buf[100000], *S = buf, *T = buf;if (S == T) {T = (S = buf) + fread(buf, 1, 100000, stdin);if (S == T) return EOF;}return *S++;
}
template<typename T>
inline void read(T &x) {static char c; x = 0; int sgn = 0;for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';if (sgn) x = -x;
}
inline void read(char *c) {for (*c = get(); *c < 'a' || *c > 'z'; *c = get());for (; *c >= 'a' && *c <= 'z'; *c = get()) ++c;*c = 0;
}namespace suffixArray {int sa[N], buc[N], x[N] , y[N];int rk[N], hgt[N];inline void pre(char *s, char *end) {int n = end - s;int m = N - 10;for (int i = 0; i < m; i++) buc[i] = 0;for (int i = 0; i < n; i++) ++buc[x[i] = s[i]];for (int i = 1; i < m; i++) buc[i] += buc[i - 1];for (int i = n - 1; i >= 0; i--) sa[--buc[x[i]]] = i;for (int k = 1; k <= n; k <<= 1) {int p = 0;for (int i = n - 1; i >= n - k; i--) y[p++] = i;for (int i = 0; i < n; i++) if (sa[i] >= k) y[p++] = sa[i] - k;for (int i = 0; i < m; i++) buc[i] = 0;for (int i = 0; i < n; i++) ++buc[x[y[i]]];for (int i = 1; i < m; i++) buc[i] += buc[i - 1];for (int i = n - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i];swap(x, y);p = 1; x[sa[0]] = 0;for (int i = 1; i < n; i++) {if (y[sa[i - 1]] == y[sa[i]] &&y[sa[i - 1] + k] == y[sa[i] + k])x[sa[i]] = p - 1;else x[sa[i]] = p++;}if (p >= n) break;m = p;}int j, k = 0;for (int i = 0; i < n; i++) rk[sa[i]] = i;for (int i = 0; i < n; i++) {if (rk[i] == 0) { hgt[0] = 0; continue; }if (k != 0) k--;int j = sa[rk[i] - 1];while (s[i + k] == s[j + k] && i + k < n && j + k < n) ++k;hgt[rk[i]] = k;}}
}
namespace trie {int tcnt;int ch[M][2];int rt[N];inline void _insert(int &u, int x, int d) {if (!u) u = ++tcnt;if (d < 0) return;_insert(ch[u][x >> d & 1], x, d - 1);}inline int _merge(int x, int y, int d) {if (!x || !y) return x ? x : y;if (d < 0) return x;ch[x][0] = _merge(ch[x][0], ch[y][0], d - 1);ch[x][1] = _merge(ch[x][1], ch[y][1], d - 1);return x;}inline int _query(int x, int y, int d) {if (d < 0) return 0;int k = y >> d & 1;if (!ch[x][k ^ 1]) return _query(ch[x][k], y, d - 1);else return (1 << d) | _query(ch[x][k ^ 1], y, d - 1);}inline void insert(int id, int x) {_insert(rt[id], x, K);}inline void merge(int from, int to) {rt[to] = _merge(rt[from], rt[to], K);}inline int query(int id, int y) {return _query(rt[id], y, K);}
}using suffixArray::sa;
using suffixArray::hgt;
using trie::insert;
using trie::query;int n, ans;
int w[N], id[N];
int fa[N], rk[N];
char s[N];
vector<int> lt[N];inline int cmp(int x, int y) {return hgt[x] > hgt[y];
}
inline int getFa(int x) {return fa[x] == x ? x : fa[x] = getFa(fa[x]);
}
inline int merge(int x, int y) {static int f1, f2;f1 = getFa(x); f2 = getFa(y);if (f1 == f2) return -1;int res = 0;if (lt[f1].size() > lt[f2].size()) swap(f1, f2);for (int x: lt[f1]) {res = max(res, query(f2, x));lt[f2].push_back(x);}lt[f1].clear();trie::merge(f1, f2);fa[f1] = f2;return res;
}int main(void) {freopen("1.in", "r", stdin);freopen("1.out", "w", stdout);read(n); read(s);for (int i = 0; i < n; i++) read(w[i]);suffixArray::pre(s, s + n);for (int i = 1; i < n; i++) id[i] = i;sort(id + 1, id + n, cmp);for (int i = 0; i < n; i++) {fa[i] = i; lt[i].push_back(w[i]);insert(i, w[i]);}for (int i = 1; i < n; i++) {int x = id[i];int res = merge(sa[x - 1], sa[x]);ans = max(ans, hgt[x] + res);}cout << ans << endl;return 0;
}

[后缀数组][trie合并][启发式合并][并查集] LOJ #6198. 谢特相关推荐

  1. BZOJ5137lg4081(广义后缀自动机,set启发式合并)

    BZOJ5137&&lg4081(广义后缀自动机,set启发式合并) 题面 自己找去 HINT 给定多个文本串,让你查询每个文本串中有多少个本质不同的子串且这个子串只出现在当前这个文本 ...

  2. BZOJ-3473 (广义后缀自动机:拓扑 or 启发式合并)

    BZOJ-3473 (广义后缀自动机:拓扑 or 启发式合并) 题目链接 题意 nnn个字符串,询问每个字符串一共有几个子串至少出现在nnn个字符串中的kkk个 思路: 拓扑 建广义后缀自动机, dp ...

  3. 2020CCPC(长春) - Ragdoll(启发式合并+带权并查集)

    题目大意:初始时给出 n 个集合,每个集合中都包含有一个数字,现在要求执行 m 次操作,每次操作分为下列三种类型: 1 x y:在 x 位置新建一个集合,并且放置一个数字 y 2 x y:合并集合 x ...

  4. P6623-[省选联考2020A卷]树【Trie,树上启发式合并】

    正题 题目链接:https://www.luogu.com.cn/problem/P6623 题目大意 一棵树,每个节点有一个权值valival_ivali​,定义disi,jdis_{i,j}dis ...

  5. BZOJ4399 魔法少女LJJ【线段树合并】【并查集】

    Description 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了 LJJ感叹道"这里真是个迷人的绿色世界,空气清新.淡雅 ...

  6. 力扣第257周赛T4数组的最大公因数排序(并查集+质因数分解)

    分析:最大公因数不为一的可以交换,而交换具有传递性.a和b可以交换,b和c可以交换则a和c也能交换.所以可交换的集合符合并查集性质.因为遍历n的平方合并会超时,可以采用分解质因数并合并根据公因数. 题 ...

  7. 采用Kruskal算法生成最小生成树,并采用并查集的合并优化和查询优化。

    文章目录 最小生成树 1.什么是图的最小生成树(MST)? 2.最小生成树用来解决什么问题? Kruskal(克鲁斯卡尔)算法 算法描述 图解 最小生成树 1.什么是图的最小生成树(MST)? 用N- ...

  8. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  9. 【01trie】【启发式合并】P6072 『MdOI R1』Path

    题意 每个点有点权,求两条没有交点的路径,使得两条路径的异或和的和最大 n ≤ 3 e 4 时 限 : 3.5 s n \le 3e4 \\ 时限:3.5s n≤3e4时限:3.5s 分析 给每个点求 ...

  10. BZOJ[2733][HNOI2012]永无乡 Splay启发式合并

    题目链接 题目大意及线段树合并解法在这里 每合并两个点,将它俩启发式合并 启发式合并,即把小的暴力往大的那里插 说按前序遍历插复杂度会极其优越?? 第k大是平衡树基本操作 代码如下: #include ...

最新文章

  1. Asp.net Mvc视频教程 页面传值基础(get/post/UpdateModel)
  2. sqlite数据库android使用教程,Android开发教程之 SQLite数据库的使用
  3. 二十六、深入HashCode与equals的区别(上篇)
  4. 如何在AS/400上发送带有颜色的MESSAGE
  5. [CQOI2015]选数(杜教筛)
  6. 神舟笔记本bios_海尔雷神(蓝天)神舟战神游戏本风扇狂转掉电大写灯狂闪维修实例...
  7. 差点令金融世界崩塌的数学公式
  8. python名称空间与运用域_Python名称空间和作用域讲座,命名,Namespaces,Scopes
  9. Java API概述及应用
  10. DELL 2400卡原装标志
  11. c语言中注释参与程序设计的编译吗,C语言程序设计(第4章函数)6
  12. 「 OptiTrack」搭建动作视觉运动捕捉系统教程
  13. 判断IP是否在IP段内
  14. 软件测试方法进行调优,一种大型软件测试方法
  15. SAR/GMTI-概述及常用抑制杂波方法DPCA
  16. python期货基本面分析_用python对股票期货做时序分析
  17. 企业电子文档管理系统哪个好?怎么选?
  18. iOS中网络编程长连接
  19. 操作系统实验二进程的创建控制实验(含代码及实验心得)
  20. 不在同一局域网的两台电脑如何通过ssh连接

热门文章

  1. eclipse建web工程的dynamic web module version 具体是什么意思
  2. 反锐化掩膜_带噪声抑制的反锐化掩模图像增强算法
  3. Tivoli基础架构管理解决方案
  4. Kotlin语言内置函数学习2:with,also,takeIf,takeUnless
  5. sequence生成器写法
  6. 乔家大院的5A牌子被摘了,但且别急着叫好
  7. vue中头像加载不出来,怎样设置默认头像
  8. systemctl status network.service命令,Failed to start LSB: Bring up/down networking.完美解决
  9. 树莓派-内核启动报错mmc0: error -5 whilst initialising MMC card
  10. 国产DeFi,困在币价里