POJ 2886Who Gets the Most Candies?(线段树)
题目大意是说有n个人围成一圈,游戏的起点是k,每个人持有一个数字(非编号)num,每次当前的人退出圈,下一个人是他左边的第num个(也就是说下一个退出的是k+num, k可以为负数,表示右边的第num个),这里的num的范围是1e9, 现在一直如果一个人是第i个推出的,那么他的得分就是i的约束的个数,球得分最高的那个人的编号
这里有两个地方稍微不好处理:
1: num < 1e9 这里只需要模拟一下就可以了,如果当前在k,往右走num,还剩下rest个人,那么下一步应该往右走num % rest,同时先使用线段树计算出当前位置的左侧和右侧还有多少人,线段树里保存的是当前区间还剩下多少个人,线段树就可以查找出下一个需要推出的人的编号
2:由于i的约数的个数是可以求出的,也就是说只需要在N内找到一个约束最大的数X,判断谁是第X个退出的就可以了。这里就用到了反素数的概念,设G[i]表示i的约数的个数,若对于任意的j,j<i有G[i] > G[j],那么i就是i反素数,这道题就转化为了球N以内的最大的反素数,设Max[i]为i以内的最大的反素数是Max[i]。在计算反素数时,设D[i]为i的约数的个数,由于对于i的一个素因子a,i除尽a后得到的a的幂是b,有D[i] = D[i/a] * (b+1) / b,而在计算D[i]时,D[i/a]已经被计算出,所以按照DP的思路,总体的复杂度就是NlonN(logN为求b时的复杂度)
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 1e9
#define inf (-((LL)1<<40))
#define lson k<<1, L, mid
#define rson k<<1|1, mid+1, R
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define FOPENIN(IN) freopen(IN, "r", stdin)
#define FOPENOUT(OUT) freopen(OUT, "w", stdout)
template<class T> T CMP_MIN(T a, T b) { return a < b; }
template<class T> T CMP_MAX(T a, T b) { return a > b; }
template<class T> T MAX(T a, T b) { return a > b ? a : b; }
template<class T> T MIN(T a, T b) { return a < b ? a : b; }
template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b; } typedef __int64 LL;
//typedef long long LL;
const int MAXN = ;
const int MAXM = ;
const double eps = 1e-;
const LL MOD = ; char name[MAXN][];
int N, K,cnt, l, r, curPos;
int num[MAXN], tree[MAXN<<], no[MAXN]; void buildTree(int k, int L, int R)
{
if(L == R) { tree[k] = ; return ; } int mid = (L + R) >> ; buildTree(lson); buildTree(rson); tree[k] = tree[k<<] + tree[k<<|];
} void update(int k, int L, int R, int x)
{
if(L == R) { tree[k] = ; no[L] = cnt; curPos = L; return ;} int mid = (L + R) >> ; if(x <= tree[k<<]) update(lson, x); else update(rson, x-tree[k<<]); tree[k] = tree[k<<] + tree[k<<|];
} int query(int k, int L, int R)
{
if(R < l || r < L) return ; if(l<=L && R<=r) return tree[k]; int mid = (L+R) >> ; return query(lson) + query(rson);
} void getNo()
{
cnt = ; int pos = K;
for(int j=;j<N-;j++)
{
update(, , N, pos);
l = ; r = curPos; int leftNum = query(, , N);
l = curPos; r = N; int rightNum = query(, , N);
int dis = abs(num[curPos]) % (N - cnt);
if(dis == ) dis = N - cnt;
if(num[curPos] > && rightNum >= dis) pos = leftNum + dis;
else if(num[curPos] > && rightNum < dis) pos = dis - rightNum;
else if(num[curPos] < && leftNum >= dis) pos = leftNum - dis + ;
else if(num[curPos] < && leftNum < dis) pos = *leftNum + rightNum - dis + ;
cnt ++;
}
for(int i=;i<=N;i++)if(!no[i]) no[i] = N;
} int isp[MAXN], yue[MAXN], D[MAXN], Max[MAXN];
void init()
{
mem1(isp);yue[] = ;
for(int i=;i<MAXN;i++) if(isp[i])
{
for(int j=*i;j<MAXN;j+=i)
{
isp[j] = ;
yue[j] = i;
}
}
D[] = Max[] = ;
for(int i=;i<MAXN;i++)
{
if(isp[i]) D[i] = ;
else
{
int last = i / yue[i];
int b = , n = i;
while(n % yue[i] == ) b ++, n /= yue[i];
D[i] = D[last] * (b+) / b;
}
if(D[i] > D[Max[i-]]) Max[i] = i;
else Max[i] = Max[i-];
}
} int main()
{
//FOPENIN("in.txt");
init();
while(~scanf("%d %d%*c", &N, &K))
{
mem0(tree); mem0(no);
buildTree(, , N);
for(int i=;i<=N;i++)
scanf("%s %d", name[i], &num[i]);
getNo();
for(int i=;i<=N;i++) if(no[i] == Max[N])
printf("%s %d\n", name[i], D[Max[N]]);
}
return ;
}
POJ 2886Who Gets the Most Candies?(线段树)的更多相关文章
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- 【POJ 2777】 Count Color(线段树区间更新与查询)
[POJ 2777] Count Color(线段树区间更新与查询) Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4094 ...
- 【POJ 2750】 Potted Flower(线段树套dp)
[POJ 2750] Potted Flower(线段树套dp) Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4566 ...
- POJ 2886.Who Gets the Most Candies? -线段树(单点更新、类约瑟夫问题)
线段树可真有意思呢续集2... 区间成段的替换和增减,以及区间求和等,其中夹杂着一些神奇的操作,数据离散化,简单hash,区间异或,还需要带着脑子来写题. 有的题目对数据的操作并不是直接按照题面意思进 ...
- POJ 2886 Who Gets the Most Candies?(线段树·约瑟夫环)
题意 n个人顺时针围成一圈玩约瑟夫游戏 每一个人手上有一个数val[i] 開始第k个人出队 若val[k] < 0 下一个出队的为在剩余的人中向右数 -val[k]个人 val[k ...
- POJ 2886 Who Gets the Most Candies? 线段树。。还有方向感
这道题不仅仅是在考察线段树,还他妹的在考察一个人的方向感.... 和线段树有关的那几个函数写了一遍就对了,连改都没改,一直在转圈的问题的出错.... 题意:从第K个同学开始,若K的数字为正 则往右转, ...
- poj 2528 Mayor's posters(线段树+离散化)
/* poj 2528 Mayor's posters 线段树 + 离散化 离散化的理解: 给你一系列的正整数, 例如 1, 4 , 100, 1000000000, 如果利用线段树求解的话,很明显 ...
- poj 2155:Matrix(二维线段树,矩阵取反,好题)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 17880 Accepted: 6709 Descripti ...
- POJ 2155 Matrix (二维线段树)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 17226 Accepted: 6461 Descripti ...
随机推荐
- 51nod1257 背包问题 V3
分数规划经典.开始精度1e-3/1e-4都不行,1e-5就A了 #include<cstdio> #include<cstring> #include<cctype> ...
- scala学习笔记(1):基本语法与容器
1 var 可变,val 不可变 var (a,b) = (10,20) 分别对a,b赋值 a=10, b=20 var a,b = (10,20)则 是a=(10,20) b=(10,20) 2 L ...
- 【解题报告】[动态规划] RQNOJ PID106 / 最大加权矩形
原题地址:http://www.rqnoj.cn/problem/106 解题思路: 一维的情况下求最大字串和的状态转移方程是:s[i]=max{s[i-1]+a[i],a[i]} 二维的情况下,只要 ...
- Heritrix源码分析(十三) Heritrix的控制中心(大脑)CrawlController(二)
本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/650744 本博客已迁移到本人独立博客: http://www.yun5u. ...
- IOS设计模式之二(门面模式,装饰器模式)
本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq) ...
- notepad 行替换使用指南
notepad++是开源的文本处理软件,性能堪比ultraedit,不过在转用notepad++之后一直为他的行替换功能纠结,UE当中只需要用 [^p] 就可以表示一行,但是在notepad++当中, ...
- HDU 4540 威威猫系列故事——打地鼠
威威猫系列故事--打地鼠 Time Limit: 300/100 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Su ...
- 记录一次cefsharp1输入法在win7下异常解决定位
最近几天都被基于cefSharp封装的浏览器控件搞疯了!对于cefSharp基本满足当前所做项目的需求,但是有一个问题一直困扰我,那就是系统中偶尔会出现输入法不能转换到中文.而且这个问题似乎没有什么规 ...
- CListCtrl总结.xml
pre{ line-height:1; color:#d1653c; background-color:#000000; font-size:16px;}.sysFunc{color:#566d68; ...
- 书签(Bookmarks)
工作台允许使用者在文件中创建书签,通过这些书签,使用者可以从书签视图里快速打开这些文件,并跳转到相应的行. (1)在编辑器左边灰色的区域里单击鼠标右键,在弹出的菜单里选择“Add Bookmark.. ...