假设已经插入了 1∼n,现在要插入 i+1,如果 i+1 插在了第 p 个数和第 p+1 个数之间(0≤p≤i),i+1 最终对应的顺序对数为 p ,逆序对数就是 i−p,我们只需要保证 ∣p−(i−p)∣≤k 即可。
记插入 i+1 时满足条件的 p 的数量为 c(i),那么可以得到:
c(i)={i+1,k+[i≡k(mod2)],i<ki≥k
于是转化为对每个 k 算 i=0∏nc(i)。
求完之后差分一下就是 maxi=1n∣f(i)−g(i)∣=k 的答案。
对单个 k 容易 O(logn) 计算,总时间复杂度 O(nlogn)。
#include<bits/stdc++.h> usingnamespace std;
typedeflonglong ll; constint N = 1e6+10; constint P = 1e9+7;
int n; ll ans[N]; ll fact[N];
voidprework(int n); ll qpow(ll a, ll b);
intmain() { cin >> n; prework(n); for(int k = 0; k < n; k++) { ans[k] = fact[k]; (ans[k] *= qpow(k+1, (n-k+1)/2)) %= P; (ans[k] *= qpow(k, (n-k)/2)) %= P; } for(int i = n-1; i > 0; i--) ans[i] = (ans[i]-ans[i-1]+P)%P; for(int i = 0; i < n; i++) cout << ans[i] << " "; }
voidprework(int n) { fact[0] = 1; for(int i = 1; i <= n; i++) fact[i] = fact[i-1]*i%P; } ll qpow(ll a, ll b) { ll ans = 1; for(; b; b >>= 1, a = a*a%P) if(b&1) ans = ans*a%P; return ans; }
串串
Description
FAT 想要烫串串。
现在有一个长度为 n 的字符串 S 与一个长度为 m 的字符串 T。
定义字符串 Si 表示将从 S 的第 i 个字符后断开得到 A,B,将 B 从尾到头形成的字符串设为 B′,将 B′ 接在 A 后面得到的字符串。
对于每个 i,FAT 想知道 T 在 Si 中出现的次数。
Input
第一行包含一个字符串 S。
第二行包含一个字符串 T。
Output
输出 n 行每行一个整数,第 i 行的数表示 T 在 Si 中出现的次数。
Hint
对于 100% 的数据,1≤m≤n≤2×106。
Solution
T 在 Si=AB′ 中的出现次数是 T 在 A 中的出现次数 + T 在 B′ 中的出现次数 + T 跨过 A 和 B′ 的出现次数。
前两个很好处理,考虑最后一个。
T 的一个后缀要与 B′ 的前缀匹配,剩余的前缀要与 A 的后缀匹配。
可以先处理出所有跟 B′ 的前缀匹配的 T 后缀,然后询问它们剩的前缀有多少个是 A 的后缀。
可以建出 KMP 的 fail tree 解决。
时间复杂度 O(nlogn)。
#include<bits/stdc++.h> usingnamespace std;
constint N = 2e6+10;
int n, m; char s[N], t[N]; int nxt[N], len[N]; int ans[N], suf[N]; int ldfn[N], rdfn[N], cnt; vector<int> ver[N];
voiddfs(int x); voidget_next(char *s, int *nxt);
namespace bit { int a[N]; #define lowbit(i) (i&-i) voidadd(int x, int v){ for(; x <= cnt; x += lowbit(x)) a[x] += v; } intquery(int x){ int ans = 0; for(; x >= 1; x -= lowbit(x)) ans += a[x]; return ans; } }
intmain() { cin >> (s+1) >> (t+1); n = strlen(s+1); m = strlen(t+1); get_next(t, nxt); for(int i = 1, j = 0; i <= n; i++) { while(j and t[j+1] != s[i]) j = nxt[j]; if(t[j+1] == s[i]) j++; len[i] = j; ans[i] = ans[i-1]+(j==m); } for(int i = 1; i <= m; i++) ver[nxt[i]].push_back(i); dfs(0); reverse(t+1, t+m+1); get_next(t, nxt); int j = 0; for(int i = 1; i <= n; i++) { while(j and t[j+1] != s[i]) j = nxt[j]; if(t[j+1] == s[i]) j++; if(j == m) suf[i-m+1] = 1; } if(j == m) j = nxt[j]; vector<int> f; for(; j; j = nxt[j]) f.push_back(j); for(int i = n; i >= 1; i--) { while(!f.empty() and i+f.back() <= n) { bit::add(ldfn[m-f.back()], 1); bit::add(rdfn[m-f.back()]+1, -1); f.pop_back(); } suf[i] += suf[i+1]; ans[i] += bit::query(ldfn[len[i]]); } for(int i = 1; i <= n; i++) cout << ans[i]+suf[i+1] << "\n"; }