【HDU 4351】Digital root【线段树】

来源:互联网 发布:个人云计算 编辑:程序博客网 时间:2024/06/05 04:31

          这道题是考验如何处理一个区间的所有子区间的问题,我们可以将其变成区间操作。

          线段树节点保存四个值,ls:表示这个区间从左起点开始的子区间的状态。rs:表示这个区间从右起点开始的子区间的状态,ts:表示这个区间中间的子区间的状态,s表示整段区间的状态。

          维护的时候就是像平时区间维护一样。

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define N 100003#define mid (l+r>>1)#define lc (d<<1)#define rc (d<<1|1)struct Tr {    int ls, rs, ts, s;}tr[N<<2];int dp[1024][1024];int root(int a) {    int tm, re = a;    while (re > 9) {        tm = re, re = 0;        while (tm) {            re += tm%10;            tm /= 10;        }    }    return re;}void init() {    int i, j, k, h;    for (i = 1;i < 1024;i++) {        for (j = 1;j < 1024;j++) {            dp[i][j] = 0;            for (k = 0;k < 10;k++) {                if (!(i&(1<<k))) continue;                for (h = 0;h < 10;h++) {                    if (!(j&(1<<h))) continue;                    dp[i][j] |= (1<<root(k+h));                }            }        }    }}void Push(int d) {    tr[d].s = dp[tr[lc].s][tr[rc].s];    tr[d].ls = tr[lc].ls|dp[tr[lc].s][tr[rc].ls];    tr[d].rs = tr[rc].rs|dp[tr[rc].s][tr[lc].rs];    tr[d].ts = tr[lc].ts|tr[rc].ts|dp[tr[lc].rs][tr[rc].ls];}void build(int d, int l, int r) {    if (l == r) {        scanf("%d", &tr[d].s);        tr[d].s = 1<<root(tr[d].s);        tr[d].ls = tr[d].rs = tr[d].ts = tr[d].s;        return;    }    build(lc, l, mid), build(rc, mid+1, r);    Push(d);}Tr query(int d, int l, int r, int L, int R) {    if (l == L && r == R) {        return tr[d];    }    if (R <= mid) return query(lc, l, mid, L, R);    else if (L > mid) return query(rc, mid+1, r, L, R);    else {        Tr tm, tl, tr;        tl = query(lc, l, mid, L, mid), tr = query(rc, mid+1, r, mid+1, R);        tm.s = dp[tl.s][tr.s];        tm.ls = tl.ls|dp[tl.s][tr.ls];        tm.rs = tr.rs|dp[tr.s][tl.rs];        tm.ts = tl.ts|tr.ts|dp[tl.rs][tr.ls];        return tm;    }}int main() {    int T, n, m, l, r, ca = 1, i, j;    scanf("%d", &T);    init();    while (T--) {        if (ca != 1) puts("");        scanf("%d", &n);        build(1, 1, n);        scanf("%d", &m);        printf("Case #%d:\n", ca++);        while (m--) {            scanf("%d%d", &l, &r);            Tr ans = query(1, 1, n, l, r);            int st = ans.ls|ans.rs|ans.ts;            j = 0;            for (i = 9;i >= 0 && j < 5;i--) {                if (st&(1<<i)) {                    if (j) printf(" ");                    printf("%d", i);                    j++;                }            }            while (j < 5) {                if (j) printf(" ");                printf("-1");                j++;            }            puts("");        }    }}


0 0
原创粉丝点击