A
最大值小于最小值就不行。
B
先将奇偶分开,偶前奇后。容易发现这样最小。
C
直接模拟,不是 (?) 的放栈里,然后稍微讨论一下即可。
D
写棵线段树模拟然后你就发现不容写线段树。。。
E
贪心从上往下取,然后倍增维护就好。
F
以后注意看到这种数据范围就像根号分治(类比虚树)。先把同一字符集的放在一组,我们发现答案最多为 (2),至少为 (1)。什么时候为 (1)?即两个串切掉 (lcp,lcs) 后有一个串是升序的。
考虑 (n) 很小,直接枚举两个串然后模拟这个过程即可,复杂度 (O(n^2|s|))。如果 (|s|) 很小,枚举每个串的每个子串,考虑有没有一个串是将这部分子串排序后的结果。但是这样会算重,我们只需把排完序后最前或最后不变的区间去掉即可。复杂度玄学 (O(n|s|^2log{s})),所以调一下根号分治的块长就好了。
代码写得非常暴力,好像后一部分复杂度是 (O(n|s|^3log{s}))。但是冲就完事。
#include <bits/stdc++.h>
#define register re
#define pc putchar
#define gc getchar
#define mp make_pair
#define pb push_back
#define pf push_front
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace Standard_IO{
template <typename T>
void read(T &x) {
T flag = 1;
char ch = gc();
for (; !isdigit(ch); ch = gc()) if (ch == '-') flag = -1;
for (x = 0; isdigit(ch); ch = gc()) x = x * 10 + ch - '0';
x *= flag;
}
template <typename T>
void write(T x) {
if (x > 9) write(x / 10);
pc(x % 10 + '0');
}
template <typename T>
void print(T x) {
if (x < 0) pc('-'), x = -x;
write(x); pc(' ');
}
}using namespace Standard_IO;
string s[200005], t;
int n;
int len;
map<string, vector<string>> cla;
unordered_map<string, bool> mark;
int main() {
read(n);
for (int i = 1; i <= n; i++) {
cin >> t;
s[i] = t;
sort(t.begin(), t.end());
cla[t].pb(s[i]);
}
len = s[1].length();
ll ans = 0, before = 0;
for (auto jzyakioi : cla) {
vector<string> now = jzyakioi.second;
n = now.size();
ans += 1ll * n * before * 1337;
before += n;
if (n <= len * 250) {
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int lcp = 0, lcs = 0;
while (now[i][lcp] == now[j][lcp]) lcp++;
while (now[i][len - lcs - 1] == now[j][len - lcs - 1]) lcs++;
bool flag1 = 1, flag2 = 1;
for (int k = lcp + 1; k < len - lcs; k++) {
if (now[i][k] < now[i][k - 1]) {
flag1 = 0;
}
if (now[j][k] < now[j][k - 1]) {
flag2 = 0;
}
}
ans += 2;
if (flag1 || flag2) ans--;
}
}
} else {
ans += 1ll * n * (n - 1);
mark.clear();
for (auto x : now) mark[x] = true;
for (auto x : now) {
for (int i = 0; i < len; i++) {
for (int j = i; j < len; j++) {
string y = x;
sort(y.begin() + i, y.begin() + j + 1);
if (y[i] != x[i] && y[j] != x[j]) {//去重
if (mark[y]) {
ans--;
}
}
}
}
}
}
}
print(ans);
return 0;
}