HDU 5812 Distance



Problem Description
In number theory, a prime is a positive integer greater than 1 that has no positive divisors other than 1 and itself. The distance between two positive integers x and y, denoted by d(x, y), is defined as the minimum number of multiplications by a prime or divisions (without a remainder) by a prime one can perform to transform x into y. For example, d(15, 50) = 3, because 50 = 15 * 2 * 5 / 3, and you have to perform two multiplications (*2, *5) and one division (/3) to transform 15 into 50.

For a set S of positive integers, which is initially empty, you are asked to implement the following types of operations on S.

1.  I x: Insert x into S. If x is already in S, just ignore this operation.
2.  D x: Delete x from S. If x is not in S, just ignore this operation.
3.  Q x: Find out a minimum z such that there exists a y in S and d(x, y) = z.
 

Input
The input contains multiple test cases. The first line of each case contains an integer Q (1 <= Q <= 50000), indicating the number of operations. The following lines each contain a letter ‘I’, ‘D’ or ‘Q’, and an integer x (1 <= x <= 1000000).
Q = 0 indicates the end of the input.
The total number of operations does not exceed 300000.
 

Output
For each case, output “Case #X:” first, where X is the case number, starting from 1. Then for each ‘Q’ operation, output the result in a line; if S is empty when a ‘Q’ operation is to perform, output -1 instead.
 

Sample Input
  
  
12 I 20 I 15 Q 30 I 30 Q 30 D 10 Q 27 I 15 D 15 D 20 D 30 Q 5 0
 

Sample Output
  
  
Case #1: 1 0 3 -1
开200w个堆来搞定插入和删除,操作的效率都是sqrt(x),把x拆了放在每个位置上,然后记下最小距离。询问的时候都找一遍就好了。
#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
#define lson x << 1, l, mid
#define rson x << 1 | 1, mid + 1, r
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const double eps = 1e-8;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int N = 1e6 + 1;
int T, n, m, t, cas = 0, x, y;
int a[N], f[N], g[N], gg[N], cnt[N], sum;
char s[2];

priority_queue<int, vector<int>, greater<int> > p[N][2];

void get_prime()
{
    cnt[1] = t = 0;
    rep(i, 2, N - 1)
    {
        if (!f[i]) { a[t++] = i; cnt[i] = 1; }
        for (int j = 0; j < t&&i*a[j] < N; j++)
        {
            f[i*a[j]] = 1;
            cnt[i*a[j]] = cnt[i] + 1;
            if (i%a[j] == 0) break;
        }
    }
}

void clear(int x)
{
    rep(i, 0, 1) while (!p[x][i].empty()) p[x][i].pop();
}

int get(int x)
{
    if (gg[x] < cas) gg[x] = cas, clear(x);
    while (!p[x][0].empty() && !p[x][1].empty() && p[x][0].top() == p[x][1].top()) p[x][0].pop(), p[x][1].pop();
    return p[x][0].empty() ? INF / 2 : p[x][0].top();
}

int main()
{
    get_prime();
    while (scanf("%d", &n), n)
    {
        printf("Case #%d:\n", ++cas);
        sum = 0;
        while (n--)
        {
            scanf("%s%d", s, &x);
            if ((s[0] == 'I' || s[0] == 'D')&&g[x] < cas) g[x] = cas, f[x] = 0;
            if (s[0] == 'I' && !f[x])
            {
                sum++;   f[x] = 1;    y = sqrt(1.0*x);
                rep(i, 1, y)
                {
                    if (x%i) continue;
                    if (gg[i] < cas) gg[i] = cas, clear(i);
                    if (gg[x / i] < cas) gg[x / i] = cas, clear(x / i);
                    if (i*i == x) p[i][0].push(cnt[i]);
                    else
                    {
                        p[i][0].push(cnt[x / i]);
                        p[x / i][0].push(cnt[i]);
                    }
                }
            }
            if (s[0] == 'D' && f[x])
            {
                sum--;   f[x] = 0;    y = sqrt(1.0*x);
                rep(i, 1, y)
                {
                    if (x%i) continue;
                    if (i*i == x) p[i][1].push(cnt[i]);
                    else
                    {
                        p[i][1].push(cnt[x / i]);
                        p[x / i][1].push(cnt[i]);
                    }
                }
            }
            if (s[0] == 'Q')
            {
                if (!sum) { printf("-1\n"); continue; }
                y = sqrt(1.0*x);
                int ans = INF;
                rep(i, 1, y)
                {
                    if (x%i) continue;
                    ans = min(ans, get(i) + cnt[x / i]);
                    ans = min(ans, get(x / i) + cnt[i]);
                }
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值