数组分块|裴蜀定理
优雅的抽象和算法设计让人泪目...
裴蜀定理
整数a、b的线性组合ax+by能表示的最小正整数是gcd(a,b),且所有可表示数都是gcd(a,b)的倍数
lc1625
枚举轮转到最左边的下标+裴蜀定理
枚举所有有效轮转(步长为gcd(b,n)),对奇下标必优化、偶下标按需优化(步长为2时),取字典序最小字符串
class Solution {
public:
string findLexSmallestString(string s, int a, int b) {
int n = s.size();
int step = gcd(b, n);
int g = gcd(a, 10);
string ans;
for (int i = 0; i < n; i += step) {
string t = s.substr(i) + s.substr(0, i);
auto modify = [&](int start) -> void {
int ch = t[start] - '0';
int inc = ch % g - ch + 10;
for (int j = start; j < n; j += 2) {
t[j] = '0' + (t[j] - '0' + inc) % 10;
}
//可以转化为的数字这部分可以 暴力枚举也行
};
modify(1);
if (step % 2)
modify(0);
if (ans.empty() || t < ans) {
ans = move(t);
}
}
return ans;
}
};
move
std::move 是C++11起的标准库函数,将对象转为右值引用,让赋值/初始化时直接“窃取”原对象资源(而非拷贝),提升效率。
BFS遍历所有“奇下标加a”“右移b位”的字符串状态,记录已访问避免重复,取字典序最小结果
class Solution {
public:
string findLexSmallestString(string s, int a, int b) {
queue<string> q{{s}};
unordered_set<string> vis{{s}};
string ans = s;
int n = s.size();
while (!q.empty()) {
s = q.front();
q.pop();
ans = min(ans, s);
string t1 = s;
for (int i = 1; i < n; i += 2) {
t1[i] = (t1[i] - '0' + a) % 10 + '0';
}
string t2 = s.substr(n - b) + s.substr(0, n - b);
for (auto& t : {t1, t2}) {
if (!vis.count(t)) {
vis.insert(t);
q.emplace(t);
}
}
}
return ans;
}
};
lc2490
class Solution {
public:
bool isCircularSentence(string s) {
if (s[0] != s.back())
return false;
for (int i = 1, n = s.length(); i < n - 1; i++)
if (s[i] == ' ' && s[i - 1] != s[i + 1])
return false;
return true;
}
};
lc1360
int year = stoi(date.substr(0, 4));
class Solution {
public:
// 判断是否为闰年
bool isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 获取某个月的天数
int daysInMonth(int year, int month) {
if (month == 2) {
return isLeapYear(year) ? 29 : 28;
}
if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
}
return 31;
}
// 将日期转换为从 0000-00-00 开始的天数
int dateToDays(string date) {
int year = stoi(date.substr(0, 4));
int month = stoi(date.substr(5, 2));
int day = stoi(date.substr(8, 2));
int totalDays = 0;
// 计算年的天数
for (int y = 0; y < year; ++y) {
totalDays += isLeapYear(y) ? 366 : 365;
}
// 计算月的天数
for (int m = 1; m < month; ++m) {
totalDays += daysInMonth(year, m);
}
// 加上日的天数
totalDays += day;
return totalDays;
}
int daysBetweenDates(string date1, string date2) {
int days1 = dateToDays(date1);
int days2 = dateToDays(date2);
return abs(days1 - days2);
}
};
分块模板
#include <bits/stdc++.h>
using namespace std;
vector<long long> a, b, lazy;
struct SqrtDecomposition {
const int block_size, n;
vector<int> ls, rs;
vector<bool> to_be_eval;
vector<vector<pair<int,int>>> first;
explicit SqrtDecomposition(const int n_)
: block_size((int)max(1.0, floor(sqrt((double)n_)))),
n((n_ + block_size - 1) / block_size) {
ls.resize(n);
rs.resize(n);
to_be_eval.assign(n, false);
first.resize(n);
for (int i = 0; i < n; ++i) {
ls[i] = block_size * i;
rs[i] = (i + 1 == n ? n_ : block_size * (i + 1));
first[i].reserve((rs[i] - ls[i]) * 2);
}
}
void rebuild_block(int b) {
vector<pair<int,int>> tmp;
tmp.reserve(rs[b] - ls[b]);
for (int i = ls[b]; i < rs[b]; ++i) tmp.emplace_back((int)a[i], i);
sort(tmp.begin(), tmp.end(), [](const pair<int,int>& x, const pair<int,int>& y){
if (x.first != y.first) return x.first < y.first;
return x.second < y.second;
});
auto &mp = first[b];
mp.clear();
mp.reserve(tmp.size());
int last_key = INT_MIN;
for (auto &p : tmp) {
if (p.first != last_key) {
last_key = p.first;
mp.emplace_back(p.first, p.second);
}
}
}
void build_maps() {
for (int b = 0; b < n; ++b) rebuild_block(b);
}
inline int get_real(int idx) const {
int blk = idx / block_size;
return (int)(a[idx] + lazy[blk]);
}
int find_leftmost_equal(int uptoIdx, int target) const {
int br = uptoIdx / block_size;
for (int b = 0; b < br; ++b) {
int key = target - (int)lazy[b];
const auto &vec = first[b];
auto it = lower_bound(vec.begin(), vec.end(), key,
[](const pair<int,int>& p, int val){ return p.first < val; });
if (it != vec.end() && it->first == key) return it->second;
}
int key_lazy = (int)lazy[br];
for (int i = ls[br]; i <= uptoIdx; ++i) {
if ((int)(a[i] + key_lazy) == target) return i;
}
return -1;
}
void range_add_and_fix(int l, int r, int val) {
if (r <= l) return;
const int b_l = l / block_size, b_r = (r - 1) / block_size;
update(l, r, val);
if (b_l == b_r) {
rebuild_block(b_l);
} else {
if (l != ls[b_l]) rebuild_block(b_l);
if (r != rs[b_r]) rebuild_block(b_r);
}
}
template <typename T>
void partial_update(const int idx, const T val) {
a[idx] += val;
b[idx / block_size] += val;
}
template <typename T>
void total_update(const int idx, const T val) {
lazy[idx] += val;
to_be_eval[idx] = true;
}
template <typename T>
void update(const int l, const int r, const T val) {
if (r <= l) return;
const int b_l = l / block_size, b_r = (r - 1) / block_size;
if (b_l < b_r) {
if (l == ls[b_l]) {
total_update(b_l, val);
} else {
for (int i = l; i < rs[b_l]; ++i) {
partial_update(i, val);
}
}
for (int i = b_l + 1; i < b_r; ++i) {
total_update(i, val);
}
if (r == rs[b_r]) {
total_update(b_r, val);
} else {
for (int i = ls[b_r]; i < r; ++i) {
partial_update(i, val);
}
}
} else {
for (int i = l; i < r; ++i) {
partial_update(i, val);
}
}
}
template <typename T>
void partial_query(const int idx, T* val) {
const int block = idx / block_size;
if (to_be_eval[block]) {
for (int i = ls[block]; i < rs[block]; ++i) {
partial_update(i, lazy[block]);
}
lazy[block] = 0;
to_be_eval[block] = false;
const_cast<SqrtDecomposition*>(this)->rebuild_block(block);
}
*val += a[idx];
}
template <typename T>
void total_query(const int idx, T* val) {
*val += b[idx] + lazy[idx] * (rs[idx] - ls[idx]);
}
template <typename T>
T query(const int l, const int r, const T id) {
const int b_l = l / block_size, b_r = (r - 1) / block_size;
T res = id;
if (b_l < b_r) {
if (l == ls[b_l]) {
total_query(b_l, &res);
} else {
for (int i = l; i < rs[b_l]; ++i) {
partial_query(i, &res);
}
}
for (int i = b_l + 1; i < b_r; ++i) {
total_query(i, &res);
}
if (r == rs[b_r]) {
total_query(b_r, &res);
} else {
for (int i = ls[b_r]; i < r; ++i) {
partial_query(i, &res);
}
}
} else {
for (int i = l; i < r; ++i) {
partial_query(i, &res);
}
}
return res;
}
};
class Solution {
public:
int longestBalanced(vector<int>& nums)
{
int n=nums.size();
int N=n+1;
SqrtDecomposition sd(N);
a.assign(N,0);
b.assign(sd.n,0);
lazy.assign(sd.n,0);
sd.build_maps();
int MAXV=100000;
vector<int> last(MAXV+1,-1);
int ans=0;
for(int r=0;r<n;r++){
int x=nums[r];
int pre=last[x];
int d=(x&1)?+1:-1;
sd.range_add_and_fix(pre+1,r+1,d);
last[x]=r;
int t=sd.get_real(r+1);
int j=sd.find_leftmost_equal(r,t);
if(j!=-1)
ans=max(ans,r-j+1);
}
return ans;
}
};