template< typename T > structINFO { int v; T w; }; // index from 1 to n template< typename T > structTree { int n, cur; std::vector< int > dfn, pos, dep, fa; std::vector< T > dis; std::vector< std::vector< INFO< T > > > adj;
Tree(int _n) { n = _n; cur = 0; dfn = std::vector< int > (_n * 2); pos = dep = fa = std::vector< int > (_n + 1); dis = std::vector< T > (_n + 1); adj = std::vector< std::vector< INFO< T > > > (_n + 1); }
voidAddEdge(int u, int v, T w = 1){ adj[u].push_back({v, w}); } voiddfs(int x, int p){ fa[x] = p; dep[x] = dep[p] + 1; dfn[++ cur] = x; pos[x] = cur; for (constauto &[y, z] : adj[x]) { if (y ^ p) { dis[y] = dis[x] + z; dfs(y, x); dfn[++ cur] = x; } } }
std::vector< int > LOG; std::vector< std::vector< int > > RMQ;
voidBuild(){ LOG = std::vector< int > (cur + 1); for (int i = 2; i <= cur; ++ i) { LOG[i] = LOG[i / 2] + 1; } RMQ = std::vector< std::vector< int > > (cur + 1, std::vector< int > (LOG[cur] + 1)); for (int i = 1; i <= cur; ++ i) { RMQ[i][0] = pos[dfn[i]]; } for (int j = 1; j <= LOG[cur]; ++ j) { for (int i = 1; i + (1 << j) - 1 <= cur; ++ i) { RMQ[i][j] = std::min(RMQ[i][j - 1], RMQ[i + (1 << (j - 1))][j - 1]); } } } intLCA(int x, int y){ // O(1) query lca x = pos[x]; y = pos[y]; if (x > y) { std::swap(x, y); } int k = LOG[y - x + 1]; return dfn[std::min(RMQ[x][k], RMQ[y - (1 << k) + 1][k])]; }
constexprint INF = 0x3f3f3f3f; template< typename T > structEdge { int from, to; T cap, flow;
Edge(int u, int v, T c, T f) : from(u), to(v), cap(c), flow(f) {} }; template< typename T > structDinic { int n, m; int Source, Sink; std::vector< Edge< T > > edges; std::vector< std::vector< int > > G; std::vector< int > d, cur; std::vector< bool > vis;
// number of vertices Dinic(int n) : n(n), d(n), cur(n), vis(n), G(n) {} voidAddEdge(int from, int to, T cap){ edges.push_back(Edge< T >(from, to, cap, 0)); edges.push_back(Edge< T >(to, from, 0, 0)); m = edges.size(); G[from].push_back(m - 2); G[to].push_back(m - 1); }
boolBFS(){ vis.assign(n, 0); std::queue< int > Q; Q.push(Source); d[Sink] = 0; vis[Source] = true; while (!Q.empty()) { int x = Q.front(); Q.pop(); for (int i = 0; i < G[x].size(); ++ i) { Edge< T > &e = edges[G[x][i]]; if (!vis[e.to] && e.cap > e.flow) { vis[e.to] = true; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[Sink]; }
T DFS(int x, T a){ if (x == Sink || a == 0) { return a; } T flow = 0, f; for (int& i = cur[x]; i < G[x].size(); ++ i) { Edge< T > &e = edges[G[x][i]]; if (d[x] + 1 == d[e.to] && (f = DFS(e.to, std::min(a, e.cap - e.flow))) > 0) { e.flow += f; edges[G[x][i] ^ 1].flow -= f; flow += f; a -= f; if (a == 0) { break; } } } return flow; }
T Maxflow(int s, int t){ this->Source = s; this->Sink = t; T flow = 0; while (BFS()) { cur.assign(n, 0); flow += DFS(Source, INF); } return flow; } };
constexprint INF = 0x3f3f3f3f; template< typename T > structEdge { int from, to; T flow, cost;
Edge(int from, int to, T flow, T cost) : from(from), to(to), flow(flow), cost(cost) {} }; template< typename T > structDinic { int n, m; int Source, Sink; std::vector< Edge< T > > edges; std::vector< std::vector< int > > G; std::vector< T > incf, d; std::vector< int > pre; std::vector< bool > vis;
// number of vertices Dinic(int n) : n(n), G(n), incf(n), d(n), pre(n), vis(n) {}
voidAddEdge(int from, int to, T flow, T cost){ edges.push_back(Edge< T >(from, to, flow, cost)); edges.push_back(Edge< T >(to, from, 0, -cost)); m = edges.size(); G[from].push_back(m - 2); G[to].push_back(m - 1); }
boolSPFA(){ d.assign(n, INF); incf.assign(n, 0); vis.assign(n, false); std::queue< int > Q; Q.push(Source); vis[Source] = true; incf[Source] = INF; d[Source] = 0; while (!Q.empty()) { int x = Q.front(); Q.pop(); vis[x] = false; for (int i = 0; i < G[x].size(); ++ i) { Edge< T > &e = edges[G[x][i]]; if (d[x] + e.cost < d[e.to] && e.flow) { d[e.to] = d[x] + e.cost; pre[e.to] = G[x][i]; incf[e.to] = std::min(incf[x], e.flow); if (!vis[e.to]) { vis[e.to] = true; Q.push(e.to); } } } } return d[Sink] != INF; }
std::pair< T, T > MCMF(int s, int t){ this->Source = s; this->Sink = t; T maxflow = 0, mincost = 0; while (SPFA()) { maxflow += incf[Sink]; mincost += incf[Sink] * d[Sink]; for (int i = Sink; i != Source; i = edges[pre[i] ^ 1].to) { edges[pre[i]].flow -= incf[Sink]; edges[pre[i] ^ 1].flow += incf[Sink]; } } return {maxflow, mincost}; } };
rmq(const vector<T> &v_) : v(v_), n(v.size()), mask(n), t(n) { for (int i = 0, at = 0; i < n; mask[i++] = at |= 1) { at = (at << 1) & ((1 << b) - 1); while (at andop(i, i - msb(at & -at)) == i) at ^= at & -at; } for (int i = 0; i < n / b; i++) t[i] = b * i + b - 1 - msb(mask[b * i + b - 1]); for (int j = 1; (1 << j) <= n / b; j++) for (int i = 0; i + (1 << j) <= n / b; i++) t[n / b * j + i] = op(t[n / b * (j - 1) + i], t[n / b * (j - 1) + i + (1 << (j - 1))]); }
intsmall(int r, int sz = b){ return r - msb(mask[r] & ((1 << sz) - 1)); }
T query(int l, int r){ if (r - l + 1 <= b) returnsmall(r, r - l + 1); int ans = op(small(l + b - 1), small(r)); int x = l / b + 1, y = r / b - 1; if (x <= y) { int j = msb(y - x + 1); ans = op(ans, op(t[n / b * j + x], t[n / b * j + y - (1 << j) + 1])); } return ans; } };
namespace lca { vector<int> g[N]; int v[2 * N], pos[N], dep[2 * N]; int t; rmq<int> RMQ;
voiddfs(int i, int d = 0, int p = -1){ v[t] = i, pos[i] = t, dep[t++] = d; for (int j : g[i]) if (j != p) { dfs(j, d + 1, i); v[t] = i, dep[t++] = d; } }
voidbuild(int n, int root){ t = 0; dfs(root); RMQ = rmq<int>(vector<int>(dep, dep + 2 * n - 1)); }
intlca(int a, int b){ a = pos[a], b = pos[b]; return v[RMQ.query(min(a, b), max(a, b))]; }
intdist(int a, int b){ return dep[pos[a]] + dep[pos[b]] - 2 * dep[pos[lca(a, b)]]; } }
vector<int> virt[N];
intbuild_virt(vector<int> v){ auto cmp = [&](int i, int j) { return lca::pos[i] < lca::pos[j]; }; sort(v.begin(), v.end(), cmp); for (int i = v.size() - 1; i; i--) v.push_back(lca::lca(v[i], v[i - 1])); sort(v.begin(), v.end(), cmp); v.erase(unique(v.begin(), v.end()), v.end()); for (int i : v) virt[i].clear(); for (int i = 1; i < v.size(); i++) { virt[lca::lca(v[i - 1], v[i])].push_back(v[i]); } return v[0]; }
structaugment_path { std::vector< std::vector< int > > g; std::vector< int > pa; // 匹配 std::vector< int > pb; std::vector< int > vis; // 访问 int n, m; // 两个点集中的顶点数量 int dfn; // 时间戳记 int res; // 匹配数
augment_path(int _n, int _m) : n(_n), m(_m) { assert(0 <= n && 0 <= m); pa = std::vector< int >(n, -1); pb = std::vector< int >(m, -1); vis = std::vector< int >(n); g.resize(n); res = 0; dfn = 0; }
voidAddEdge(int from, int to){ assert(0 <= from && from < n && 0 <= to && to < m); g[from].push_back(to); }
booldfs(int v){ vis[v] = dfn; for (int u : g[v]) { if (pb[u] == -1) { pb[u] = v; pa[v] = u; returntrue; } } for (int u : g[v]) { if (vis[pb[u]] != dfn && dfs(pb[u])) { pa[v] = u; pb[u] = v; returntrue; } } returnfalse; }
std::pair< int, std::vector< int > > find_max_unweighted_matching() { while (true) { ++ dfn; int cnt = 0; for (int i = 0; i < n; ++ i) { if (pa[i] == -1 && dfs(i)) { ++ cnt; } } if (cnt == 0) { break; } res += cnt; } return {res, pa}; } };
template< typename T > structhungarian { // km int n; std::vector< int > matchx; // 左集合对应的匹配点 std::vector< int > matchy; // 右集合对应的匹配点 std::vector< int > pre; // 连接右集合的左点 std::vector< bool > visx; // 拜访数组 左 std::vector< bool > visy; // 拜访数组 右 std::vector< T > lx; std::vector< T > ly; std::vector< std::vector< T > > g; std::vector< T > slack; T inf; T res; std::queue< int > q; int org_n; int org_m;
hungarian(int _n, int _m) { org_n = _n; org_m = _m; n = std::max(_n, _m); inf = std::numeric_limits< T >::max(); res = 0; g = std::vector< std::vector< T > >(n, std::vector< T >(n)); matchx = std::vector< int >(n, -1); matchy = std::vector< int >(n, -1); pre = std::vector< int >(n); visx = std::vector< bool >(n); visy = std::vector< bool >(n); lx = std::vector< T >(n, -inf); ly = std::vector< T >(n); slack = std::vector< T >(n); }
voidAddEdge(int u, int v, T w){ g[u][v] = std::max(w, 0); // 负值还不如不匹配 因此设为0不影响 }
boolcheck(int v){ visy[v] = true; if (matchy[v] != -1) { q.push(matchy[v]); visx[matchy[v]] = true; // in S returnfalse; } // 找到新的未匹配点 更新匹配点 pre 数组记录着"非匹配边"上与之相连的点 while (v != -1) { matchy[v] = pre[v]; std::swap(v, matchx[pre[v]]); } returntrue; }
voidbfs(int i){ while (!q.empty()) { q.pop(); } q.push(i); visx[i] = true; while (true) { while (!q.empty()) { int u = q.front(); q.pop(); for (int v = 0; v < n; ++ v) { if (!visy[v]) { T delta = lx[u] + ly[v] - g[u][v]; if (slack[v] >= delta) { pre[v] = u; if (delta) { slack[v] = delta; } elseif (check(v)) { // delta=0 代表有机会加入相等子图 找增广路 // 找到就return 重建交错树 return; } } } } } // 没有增广路 修改顶标 T a = inf; for (int j = 0; j < n; ++ j) { if (!visy[j]) { a = std::min(a, slack[j]); } } for (int j = 0; j < n; ++ j) { if (visx[j]) { // S lx[j] -= a; } if (visy[j]) { // T ly[j] += a; } else { // T' slack[j] -= a; } } for (int j = 0; j < n; ++ j) { if (!visy[j] && slack[j] == 0 && check(j)) { return; } } } }
std::pair< T, std::vector< int > > find_max_weighted_matching() { // 初始顶标 for (int i = 0; i < n; ++ i) { for (int j = 0; j < n; ++ j) { lx[i] = std::max(lx[i], g[i][j]); } }
for (int i = 0; i < n; ++ i) { fill(slack.begin(), slack.end(), inf); fill(visx.begin(), visx.end(), false); fill(visy.begin(), visy.end(), false); bfs(i); }
// custom for (int i = 0; i < n; ++ i) { if (g[i][matchx[i]] > 0) { res += g[i][matchx[i]]; } else { matchx[i] = -1; } } /* std::cout << res << "\n"; for (int i = 0; i < org_n; i++) { std::cout << matchx[i] + 1 << " \n"[i + 1 == org_n]; } */ return {res, matchx}; } };
// graph template< typename T > classgraph { public: structedge { int from; int to; T cost; };
std::vector< edge > edges; std::vector< std::vector< int > > g; int n;
graph(int _n) : n(_n) { g.resize(n); }
virtualintadd(int from, int to, T cost)= 0; };
// undirectedgraph template< typename T > classundirectedgraph : public graph< T > { public: using graph< T >::edges; using graph< T >::g; using graph< T >::n;
undirectedgraph(int _n) : graph< T >(_n) {}
intAddEdge(int from, int to, T cost = 1){ assert(0 <= from && from < n && 0 <= to && to < n); int id = (int) edges.size(); g[from].push_back(id); g[to].push_back(id); edges.push_back({from, to, cost}); return id; } };
// blossom / find_max_unweighted_matching template< typename T > std::vector< int > find_max_unweighted_matching(const undirectedgraph< T > &g){ std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count()); std::vector< int > match(g.n, -1); // 匹配 std::vector< int > aux(g.n, -1); // 时间戳记 std::vector< int > label(g.n); // "o" or "i" std::vector< int > orig(g.n); // 花根 std::vector< int > parent(g.n, -1); // 父节点 std::queue< int > q; int aux_time = -1;
auto lca = [&](int v, int u) { aux_time++; while (true) { if (v != -1) { if (aux[v] == aux_time) { // 找到拜访过的点 也就是LCA return v; } aux[v] = aux_time; if (match[v] == -1) { v = -1; } else { v = orig[parent[match[v]]]; // 以匹配点的父节点继续寻找 } } std::swap(v, u); } }; // lca
auto blossom = [&](int v, int u, int a) { while (orig[v] != a) { parent[v] = u; u = match[v]; if (label[u] == 1) { // 初始点设为"o" 找增广路 label[u] = 0; q.push(u); } orig[v] = orig[u] = a; // 缩花 v = parent[u]; } }; // blossom
auto augment = [&](int v) { while (v != -1) { int pv = parent[v]; int next_v = match[pv]; match[v] = pv; match[pv] = v; v = next_v; } }; // augment
auto bfs = [&](int root) { fill(label.begin(), label.end(), -1); iota(orig.begin(), orig.end(), 0); while (!q.empty()) { q.pop(); } q.push(root); // 初始点设为 "o", 这里以"0"代替"o", "1"代替"i" label[root] = 0; while (!q.empty()) { int v = q.front(); q.pop(); for (int id : g.g[v]) { auto &e = g.edges[id]; int u = e.from ^ e.to ^ v; if (label[u] == -1) { // 找到未拜访点 label[u] = 1; // 标记 "i" parent[u] = v; if (match[u] == -1) { // 找到未匹配点 augment(u); // 寻找增广路径 returntrue; } // 找到已匹配点 将与她匹配的点丢入queue 延伸交错树 label[match[u]] = 0; q.push(match[u]); continue; } elseif (label[u] == 0 && orig[v] != orig[u]) { // 找到已拜访点 且标记同为"o" 代表找到"花" int a = lca(orig[v], orig[u]); // 找LCA 然后缩花 blossom(u, v, a); blossom(v, u, a); } } } returnfalse; }; // bfs
auto greedy = [&]() { std::vector< int > order(g.n); // 随机打乱 order iota(order.begin(), order.end(), 0); shuffle(order.begin(), order.end(), rng);
// 将可以匹配的点匹配 for (int i : order) { if (match[i] == -1) { for (auto id : g.g[i]) { auto &e = g.edges[id]; int to = e.from ^ e.to ^ i; if (match[to] == -1) { match[i] = to; match[to] = i; break; } } } } }; // greedy
// 一开始先随机匹配 greedy(); // 对未匹配点找增广路 for (int i = 0; i < g.n; i++) { if (match[i] == -1) { bfs(i); } } return match; }
int n, k; std::cin >> n >> k; std::vector< int > a(n), Max(n), Min(n); for (auto &x : a) { std::cin >> x; } std::deque< int > p, q; for (int i = 0; i < n; ++ i) { while (!q.empty() && a[q.back()] >= a[i]) { q.pop_back(); } q.push_back(i); if (q.back() - q.front() >= k) { q.pop_front(); } if (i >= k - 1) { Min[i] = a[q.front()]; }
while (!p.empty() && a[p.back()] < a[i]) { p.pop_back(); } p.push_back(i); if (p.back() - p.front() >= k) { p.pop_front(); } if (i >= k - 1) { Max[i] = a[p.front()]; } } for (int i = k - 1; i < n; ++ i) { std::cout << Min[i] << " \n"[i + 1 == n]; } for (int i = k - 1; i < n; ++ i) { std::cout << Max[i] << " \n"[i + 1 == n]; } return0; }
template< typename T > structFenWick { int n; std::vector< T > c; FenWick(int n) : n(n), c(n + 1) {} voidadd(int i, T d){ for (; i <= n; i += i & -i) { c[i] += d; } } voidadd(int l, int r, T d){ add(l, d); add(r + 1, -d); } T get(int i){ T sum = 0; for (; i; i -= i & -i) { sum += c[i]; } return sum; } T get(int l, int r){ returnget(r) - get(l - 1); } };
template< typename T > structFenwick { int n, m; std::vector< vector< T > > c; Fenwick(int n, int m) : n(n), m(m), c(n + 1, vector< T > (m + 1)) {} voidadd(int x, int y, T d){ for (; x <= n; x += x & -x) { for (; y <= m; y += y & -y) { c[x][y] += d; } } } voidadd(int x1, int y1, int x2, int y2, T d){ add(x1, y1, d); add(x1, y2 + 1, -d); add(x2 + 1, y1, -d); add(x2 + 1, y2 + 1, d); } T get(int x, int y, T sum = 0){ for (; x; x -= x & -x) { for (; y; y -= y & -y) { sum += c[x][y]; } } return sum; } T get(int x1, int y1, int x2, int y2){ returnget(x2, y2) - get(x1 - 1, y2) - get(x2, y1 - 1) + get(x1 - 1, y1 - 1); } };
template< typename T > structFenwick { int n, m; std::vector< vector< T > > c1, c2, c3, c4; Fenwick(int n, int m) : n(n), m(m), c1(n + 1, vector< T > (m + 1)), c2(c1), c3(c1), c4(c1) {} voidadd(int x, int y, T d){ for (int i = x; i <= n; i += i & -i) { for (int j = y; j <= m; j += j & -j) { c1[i][j] += d; c2[i][j] += x * d; c3[i][j] += y * d; c4[i][j] += x * y * d; } } } voidadd(int x1, int y1, int x2, int y2, T d){ add(x1, y1, d); add(x1, y2 + 1, -d); add(x2 + 1, y1, -d); add(x2 + 1, y2 + 1, d); } T get(int x, int y, T sum = 0){ for (int i = x; i; i -= i & -i) { for (int j = y; j; j -= j & -j) { sum += (x + 1) * (y + 1) * c1[i][j]; sum -= (y + 1) * c2[i][j]; sum -= (x + 1) * c3[i][j]; sum += c4[i][j]; } } return sum; } T get(int x1, int y1, int x2, int y2){ returnget(x2, y2) - get(x1 - 1, y2) - get(x2, y1 - 1) + get(x1 - 1, y1 - 1); } };
structInfo { int cnt; Info() : cnt(0) {} friend Info operator + (const Info &l, const Info &r) { Info rt; rt.cnt = l.cnt + r.cnt; return rt; } }; int n, q, a[N], col[N], rt[N]; set< int > s; set< int >::iterator it; structSegmentTree { int tot; int col[N]; int ls[N << 5], rs[N << 5], rub[N << 5], Bottom; Info inf[N << 5];
SegmentTree() : tot(0), Bottom(0) {} // 新开节点 intNew(){ return Bottom ? rub[Bottom --] : ++ tot; } // 删除节点 voidDelete(int &x){ ls[x] = rs[x] = 0; inf[x] = Info(); rub[++ Bottom] = x; x = 0; } voidPush_Up(int x){ inf[x] = inf[ls[x]] + inf[rs[x]]; } // 使树x里权值为pos的个数增加k voidModify(int &x, int l, int r, int pos, LL k){ if (!x) { x = New(); } if (l == r) { inf[x].cnt += k; return; } int mid = (l + r) >> 1; if (pos <= mid) { Modify(ls[x], l, mid, pos, k); } else { Modify(rs[x], mid + 1, r, pos, k); } Push_Up(x); } // 合并xy intMerge(int x, int y, int l, int r){ if (!x || !y) { return x | y; } int z = New(); if (l == r) { inf[z] = inf[x] + inf[y]; } else { int mid = (l + r) >> 1; ls[z] = Merge(ls[x], ls[y], l, mid); rs[z] = Merge(rs[x], rs[y], mid + 1, r); Push_Up(z); Delete(x); // 删除,看情况 Delete(y); } return z; } // 将树x的[ql,qr]里的信息分裂到树y里 voidSplit(int &x, int &y, int l, int r, int ql, int qr){ if (ql > qr || ql > r || qr < l) { return; } if (ql <= l && r <= qr) { y = x; x = 0; return; } y = ++ tot; int mid = (l + r) >> 1; Split(ls[x], ls[y], l, mid, ql, qr); Split(rs[x], rs[y], mid + 1, r, ql, qr); Push_Up(x); Push_Up(y); } // 前k个给x,其余给y voidsplit(int p, int &x, int &y, int l, int r, int k){ if (!p) { x = y = 0; return; } if (l == r) { // 断边 if (k) { x = p; y = 0; } else { y = p; x = 0; } return; } int mid = (l + r) >> 1; if (inf[ls[p]].cnt >= k) { // 右儿子给y, 递归左儿子 y = p; x = New(); split(ls[p], ls[x], ls[y], l, mid, k); } else { // 左儿子给x, 递归右儿子 x = p; y = New(); split(rs[p], rs[x], rs[y], mid + 1, r, k - inf[ls[p]].cnt); } Push_Up(x); Push_Up(y); } // 在树x里查询第k大 intQuery_Kth(int x, int l, int r, int k){ if (l == r) { return l; } int mid = (l + r) >> 1; if (inf[ls[x]].cnt >= k) { returnQuery_Kth(ls[x], l, mid, k); } returnQuery_Kth(rs[x], mid + 1, r, k - inf[ls[x]].cnt); } // 在树x里查询[ql,qr]的个数和 LL Query_Cnt(int x, int l, int r, int ql, int qr){ if (ql > qr || ql > r || qr < l) { return0; } if (ql <= l && r <= qr) { return inf[x].cnt; } int mid = (l + r) >> 1; returnQuery_Cnt(ls[x], l, mid, ql, qr) + Query_Cnt(rs[x], mid + 1, r, ql, qr); } intquery(int x, int l, int r){ if (l == r) { return l; } int mid = (l + r) >> 1; if (inf[ls[x]].cnt) { returnquery(ls[x], l, mid); } returnquery(rs[x], mid + 1, r); } // 将区间分裂成[l,x]和(x,r] voidsplit(int p){ it = s.lower_bound(p); if (*it == p) { return; } int r = *it, l = *prev(it) + 1; if (col[r]) { split(rt[r], rt[r], rt[p], 1, n, r - p); } else { split(rt[r], rt[p], rt[r], 1, n, p - l + 1); } col[p] = col[r]; s.insert(p); } // 区间排序,0升序,1降序 voidSort(int l, int r, int op){ split(l - 1); split(r); int x = 0; for (it = s.lower_bound(l); *it <= r;) { x = Merge(x, rt[*it], 1, n); rt[*it] = 0; set< int >::iterator IT = it; ++ it; s.erase(IT); } rt[r] = x; col[r] = op; s.insert(r); } } st;
#include<bits/stdc++.h> usingnamespace std; using LL = longlong; constint N = 5e5 + 5, MOD = 998244353, INF = 0x3f3f3f3f;
int n, m, a[N], b[N], tot; vector< int > pos[N]; int st[N], ed[N], belong[N], siz[N], num; int f[720][720], cnt[N], idx[N]; intQuery(int l, int r){ int x = belong[l], y = belong[r], ans = 0; if (x == y) { for (int i = l; i <= r; ++ i) cnt[a[i]] = 0; for (int i = l; i <= r; ++ i) ans = max(ans, ++ cnt[a[i]]); return ans; } ans = f[x + 1][y - 1]; for (int i = l; i <= ed[x]; ++ i) { while (idx[i] + ans < pos[a[i]].size() && pos[a[i]][idx[i] + ans] <= r) ++ ans; } for (int i = st[y]; i <= r; ++ i) { while (idx[i] - ans >= 0 && pos[a[i]][idx[i] - ans] >= l) ++ ans; } return ans; } signedmain(){ cin.tie(nullptr)->sync_with_stdio(false);
cin >> n >> m; for (int i = 1; i <= n; ++ i) { cin >> a[i]; b[i] = a[i]; } sort(b + 1, b + n + 1); tot = unique(b + 1, b + n + 1) - (b + 1); for (int i = 1; i <= n; ++ i) { a[i] = lower_bound(b + 1, b + tot + 1, a[i]) - b; pos[a[i]].push_back(i); idx[i] = (int)pos[a[i]].size() - 1; } num = sqrt(n); for (int i = 1; i <= num; ++ i) { st[i] = n / num * (i - 1) + 1; ed[i] = n / num * i; } ed[num] = n; for (int i = 1; i <= num; ++ i) { for (int j = st[i]; j <= ed[i]; ++ j) { belong[j] = i; } siz[i] = ed[i] - st[i] + 1; memset(cnt, 0, sizeof cnt); for (int j = i; j <= num; ++ j) { f[i][j] = f[i][j - 1]; for (int k = st[j]; k <= ed[j]; ++ k) { f[i][j] = max(f[i][j], ++ cnt[a[k]]); } } } int lastans = 0; while (m -- ) { int l, r; cin >> l >> r; l ^= lastans; r ^= lastans; cout << (lastans = Query(l, r)) << '\n';
vector<int> z_function(string s){ int n = (int) s.length(); vector<int> z(n); for (int i = 1, l = 0, r = 0; i < n; ++i) { if (i <= r && z[i - l] < r - i + 1) { z[i] = z[i - l]; } else { z[i] = max(0, r - i + 1); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) { ++z[i]; } } if (i + z[i] - 1 > r) { l = i; r = i + z[i] - 1; } } return z; }
#include<bits/stdc++.h> usingnamespace std; using LL = longlong; constint N = 4e5 + 5, MOD = 1e9 + 7;
int n, a[N]; structSegTree { int len, cnt; } st[N << 2]; SegTree operator + (const SegTree &l, const SegTree &r) { if (!l.len || r.len > l.len) return r; if (!r.len || l.len > r.len) return l; return {l.len, (l.cnt + r.cnt) % MOD}; } voidbuild(int x, int l, int r){ if (l == r) { st[x] = {0, 1}; return; } int mid = (l + r) >> 1; build(x << 1, l, mid); build(x << 1 | 1, mid + 1, r); st[x] = st[x << 1] + st[x << 1 | 1]; } voidupdate(int x, int l, int r, int pos, const SegTree &val){ if (l == r) { st[x] = val; return; } int mid = (l + r) >> 1; if (pos <= mid) update(x << 1, l, mid, pos, val); else update(x << 1 | 1, mid + 1, r, pos, val); st[x] = st[x << 1] + st[x << 1 | 1]; } SegTree query(int x, int l, int r, int ql, int qr){ if (ql > qr || ql > r || qr < l) return {0, 1}; if (ql <= l && r <= qr) return st[x]; int mid = (l + r) >> 1; returnquery(x << 1, l, mid, ql, qr) + query(x << 1 | 1, mid + 1, r, ql, qr); } int b[N], m; signedmain(){ cin.tie(nullptr)->sync_with_stdio(false);
cin >> n; for (int i = 1; i <= n; ++ i) { cin >> a[i]; b[i] = a[i]; } sort(b + 1, b + n + 1); m = unique(b + 1, b + n + 1) - (b + 1); build(1, 1, m); int max_len = 0; for (int i = 1; i <= n; ++ i) { a[i] = lower_bound(b + 1, b + m + 1, a[i]) - b; auto x = query(1, 1, m, 1, a[i] - 1); ++ x.len; max_len = max(max_len, x.len); auto y = query(1, 1, m, a[i], a[i]); // 当且仅当f[j]+1=f[i]才能将其合并 update(1, 1, m, a[i], x + y); // auto z = query(1, 1, m, a[i], a[i]); // cout << z.len << ' ' << z.cnt << '\n'; } int ans = 0; for (int i = 1; i <= m; ++ i) { auto x = query(1, 1, m, i, i); if (x.len == max_len) ans = (ans + x.cnt) % MOD; } cout << ans << '\n'; return0; }
LL ans = 0; for (int x = 1, gx; x <= n; x = gx + 1) { gx = k / x ? min(k / (k / x), n) : n; ans -= 1LL * (k / x) * (x + gx) * (gx - x + 1) / 2; }
扩展欧几里得算法
对于任意整数$a, b$,存在一对整数$x,y$,满足$a \cdot x \rm + b \cdot y= \gcd (a,b)$
1 2 3 4 5 6
voidexGCD(int a, int b, int &x, int &y){ if (b == 0) { x = 1, y = 0; return a;} int d = exGCD(b, a % b, x, y); int z = x; x = y; y = z - y * (a / b); return d; }
constexprint P = 998244353; // assume -P <= x < 2P intnorm(int x){ if (x < 0) { x += P; } if (x >= P) { x -= P; } return x; } template<class T> T power(T a, LL b){ T res = 1; for (; b; b /= 2, a *= a) { if (b % 2) { res *= a; } } return res; } structMint { int x; Mint(int x = 0) : x(norm(x)) {} Mint(LL x) : x(norm(x % P)) {} intval()const{ return x; } Mint operator-() const { returnMint(norm(P - x)); } Mint inv()const{ assert(x != 0); returnpower(*this, P - 2); } Mint &operator*=(const Mint &rhs) { x = LL(x) * rhs.x % P; return *this; } Mint &operator+=(const Mint &rhs) { x = norm(x + rhs.x); return *this; } Mint &operator-=(const Mint &rhs) { x = norm(x - rhs.x); return *this; } Mint &operator/=(const Mint &rhs) { return *this *= rhs.inv(); } friend Mint operator*(const Mint &lhs, const Mint &rhs) { Mint res = lhs; res *= rhs; return res; } friend Mint operator+(const Mint &lhs, const Mint &rhs) { Mint res = lhs; res += rhs; return res; } friend Mint operator-(const Mint &lhs, const Mint &rhs) { Mint res = lhs; res -= rhs; return res; } friend Mint operator/(const Mint &lhs, const Mint &rhs) { Mint res = lhs; res /= rhs; return res; } friend std::istream &operator>>(std::istream &is, Mint &a) { LL v; is >> v; a = Mint(v); return is; } friend std::ostream &operator<<(std::ostream &os, const Mint &a) { return os << a.val(); } };