?合計クエリCodeForces - 1217E(セグメント木)
質問の意味:
これは、の集合として定義される\(平衡\) 、および場合にのみ桁の各セットの数の和は、ビットが同じ数に設定されている場合。それ以外の場合は、コレクションが呼び出された\(\アンバランス)それがあります。
長所与(N- \)\のシーケンス、\(Q \)質問および最小の数内の時間間隔\(不平衡\)設定された出力デジタル和。何も出力がない場合、\(--1は\) 。
\(N、Q <= 200000 \) 。
ソリューション:
見つけることができますがあれば、(アンバランス\)\コレクションを、最小はちょうど2つの数字の集まりで構成されなければなりません。これら2つの数の存在は、10進数字ではありません\(0 \) 。
10本のツリーラインの確立は、この非メンテナンスのビット各位置(0 \)\最小を更新するときの間隔最小値は、答えを更新します。クエリ間隔が別途必要な場合は、クエリは、また、互いに影響を分離した後、複数のセクション間の数字を忘れていない場合は、各桁を列挙すべきで、最小は答えを更新するために、複数の間隔をマージします。
時間複雑度\(O(10×(N-M +)ログ(N))\) 。
コード:
#include <bits/stdc++.h>
#define fopi freopen("in.txt", "r", stdin)
#define fopo freopen("out.txt", "w", stdout)
using namespace std;
const int inf = 2e9 + 10;
const int maxn = 2e5 + 10;
struct Node {
int l, r, Min[12];
}t[maxn*4];
int Ans[maxn*4], a[maxn], tmp[maxn];
int ans;
void push_up(int id) {
Ans[id] = inf;
for (int i = 1; i <= 10; i++) {
if (t[id*2].Min[i] < inf && t[id*2+1].Min[i] < inf)
Ans[id] = min(Ans[id], t[id*2].Min[i] + t[id*2+1].Min[i]);
t[id].Min[i] = min(t[id*2].Min[i], t[id*2+1].Min[i]);
}
Ans[id] = min(Ans[id], min(Ans[id*2], Ans[id*2+1]));
}
void build(int id, int l, int r) {
Ans[id] = inf;
t[id].l = l, t[id].r = r;
if (l == r) {
int res = a[l];
for (int i = 1; i <= 10; i++) {
if (res % 10 == 0) t[id].Min[i] = inf;
else t[id].Min[i] = a[l];
res /= 10;
}
return;
}
int mid = (l+r) / 2;
build(id*2, l, mid), build(id*2+1, mid+1, r);
push_up(id);
}
void update(int id, int l, int x) {
if (t[id].l == l && t[id].r == l) {
int res = x;
for (int i = 1; i <= 10; i++) {
if (res % 10 == 0) t[id].Min[i] = inf;
else t[id].Min[i] = x;
res /= 10;
}
return;
}
int mid = (t[id].l + t[id].r) / 2;
if (l <= mid) update(id*2, l, x);
else update(id*2+1, l, x);
push_up(id);
}
void query(int id, int l, int r) {
if (l <= t[id].l && r >= t[id].r) {
for (int i = 1; i <= 10; i++) {
if (tmp[i] < inf && t[id].Min[i] < inf) {
ans = min(ans, tmp[i] + t[id].Min[i]);
}
tmp[i] = min(tmp[i], t[id].Min[i]);
}
ans = min(ans, Ans[id]);
return;
}
int mid = (t[id].l + t[id].r) / 2;
if (r <= mid) query(id*2, l, r);
else if (l > mid) query(id*2+1, l, r);
else query(id*2, l, mid), query(id*2+1, mid+1, r);
}
int n, m, res;
int main() {
//fopi;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
build(1, 1, n);
for (int i = 1; i <= m; i++) {
int op, x, y;
scanf("%d%d%d", &op, &x, &y);
if (op == 1) update(1, x, y);
else {
for (int i = 1; i <= 10; i++) tmp[i] = inf;
ans = inf;
query(1, x, y);
printf("%d\n", ans >= inf ? -1 : ans);
}
}
}