hdu 4630 No Pain No Game (区间gcd相关x线段树or树状数组)

来源:互联网 发布:mac os x dmg vmware 编辑:程序博客网 时间:2024/05/08 04:01

题意:
给定1-n的一个排列。
在一段区间,找两个位置不同的数,使得gcd最大。
思路:
因为给的序列很特殊。
首先容易想到,对1-n每个数作为约数维护一个状态。
把序列中x的倍数,按原来的位置,过滤出来。
对一个询问li, ri
如果其中至少有两个落到[li, ri]区间中,则x为一个可能值。
考虑将询问按右端点从小到大排序。
last[x]保存x最近出现的位置,初始为0
c[i]存的是一个潜在最大gcd,在i的右边存在一个数,与ai的gcd是ci
从左到右扫一遍序列,当遍历到ai时
对ai的因子x, 如果last[x]!=0 ,则可以把用x来更新ci,然后更新last
处理询问,就在区间内查询ci的最大值就行了。。

const int N = 50005;int ai[N], last[N], ans[N], n;int tr[N<<2], qL, qR;#define lc o<<1#define rc o<<1|1void update(int o, int l, int r, int x, int v) {    if ( l == r ) {        tr[o] = max(v, tr[o]); return;    }    int m = (l + r) >> 1;    if ( x <= m )        update(lc, l, m, x, v);    else        update(rc, m+1, r, x, v);    tr[o] = max ( tr[lc], tr[rc] );}int query(int o, int l, int r) {    if ( qL <= l && r <= qR ) return tr[o];    int m = (l + r) >> 1;    if ( qR <= m )        return query(lc, l, m);    else if ( qL > m )        return query(rc, m+1, r);    return max ( query(lc, l, m), query(rc, m+1, r) );}struct Q {    int l, r, id;    bool operator < (const Q& rhs) const {        return r < rhs.r;    }} queries[N];int main() {#ifdef _LOCA_ENV_    freopen("input.in", "r", stdin);#endif // _LOCA_ENV    int t, q;    scanf("%d", &t);    while ( t -- ) {        scanf("%d", &n);        rep(i, 1, n) {            scanf("%d", ai + i);        }        scanf("%d", &q);        rep(i, 0, q-1) {            int l, r;            scanf("%d%d", &l, &r);            queries[i] = (Q) {l, r, i};        }        sort(queries, queries + q);        memset(last, 0, sizeof(last));        memset(tr, 0, sizeof(tr));        int j = 0;        for (int i = 1; i <= n; ++ i) {            for (int x = 1; x * x <= ai[i]; ++ x)                if ( ai[i] % x == 0 ) {                    if ( last[x] != 0 ) {                        update(1, 1, n, last[x], x);                    }                    last[x] = i;                    int y = ai[i] / x;                    if ( y != x ) {                        if ( last[y] != 0 ) {                            update(1, 1, n, last[y], y);                        }                        last[y] = i;                    }                }            while ( j < q && queries[j].r == i ) {                if ( queries[j].l == queries[j].r ) {                    ans[queries[j].id] = 0;                } else {                    qL = queries[j].l, qR = queries[j].r;                    ans[queries[j].id] = query(1, 1, n);                }                ++ j;            }        }        rep(i, 0, q-1) printf("%d\n", ans[i]);    }    return 0;}
0 0
原创粉丝点击