POJ 2886 - Who Gets the Most Candies?

由於模擬約瑟夫環比較費時,可以利用線段樹的查詢功能來優化。
如下圖,把一個環拆開變成一條直線,就可以查詢某段區間有多少個空位置了。
這裏寫圖片描述
反素數經典博文:打開連接


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <map>
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
int maxn[500001 << 2], v[500005];
char ch[500005][10], cc[500005][10];
int a[100] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53}, ans, temp, n, k;
void dfs(int deep, int limit, int tmp, int num)
{
    if(tmp > n) return ;
    if(num > ans)
    {
        ans = num;
        temp = tmp;
    }
    else if(num == ans && tmp < temp)
    {
        temp = tmp;
    }
    for(int i = 1; i <= limit; i++)
    {
        if(tmp > n / a[deep]) break;
        dfs(deep + 1, i, tmp * a[deep], num * (i + 1));
        tmp *= a[deep];
    }
}
void build(int l, int r, int rt)
{
    if(l == r)
    {
        maxn[rt] = 1;
        return ;
    }
    int mid = (l + r) >> 1;
    build(l, mid, lson);
    build(mid + 1, r, rson);
    maxn[rt] = maxn[lson] + maxn[rson];
}
int query(int l, int r, int rt, int L, int R)
{
    if(L <= l && R >= r)
    {
        return maxn[rt];
    }
    int mid = (l + r) >> 1;
    int ans = 0;
    if(mid >= L) ans = query(l, mid, lson, L, R);
    if(mid < R) ans += query(mid + 1, r, rson, L, R);
    return ans;
}
int update(int l, int r, int rt, int where)
{
    if(l == r)
    {
        maxn[rt] = 0;
        return l;
    }
    int mid = (l + r) >> 1;
    int ans = 0;
    if(maxn[lson] >= where) ans = update(l, mid, lson, where);
    else ans = update(mid + 1, r, rson, where - maxn[lson]);
    --maxn[rt];
    return ans;
}
int main()
{
    while(~scanf("%d %d", &n, &k))
    {
        dfs(0, 60, 1, 1);
        for(int i = 1; i <= n; i++)
        {
            scanf("%s %d", ch[i], &v[i]);
        }
        int tmp = k;
        build(1, n, 1);
        strcpy(cc[1], ch[tmp]);
        update(1, n, 1, tmp);
        for(int i = 2; i <= n; i++)
        {
            if(v[tmp] > 0)
                v[tmp] = (v[tmp] - 1) % maxn[1] + 1;
            else
                v[tmp] = maxn[1] + 1 - (-v[tmp] - 1) % maxn[1] - 1;
            int k = query(1, n, 1, tmp + 1, n);
            if(v[tmp] <= k) tmp = update(1, n, 1, maxn[1] - k + v[tmp]);
            else tmp = update(1, n, 1, maxn[1] - k + 1 - (maxn[1] + 1 - v[tmp]));
            strcpy(cc[i], ch[tmp]);
        }
        printf("%s %d\n", cc[temp], ans);
    }
    return 0;
}
發佈了130 篇原創文章 · 獲贊 6 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章