题意:一堆小朋友围成一个圈,规定从k开始玩,每个被选中的人都有一个数字,正数代表从他左边开始数num,负数从右边数,被选中的人继续按照上述操作,直到都退出圈子,第i个退圈的人能拿到一个点数,这个点数是i的因数个数(比如第4个人拿3点)。问:谁点数最多,一样多选第一个。

思路:一道好题啊,万万没想到是线段树,想要想到感觉还是有点难度的。这道题其实就是要一直维护剩余人数,但是以前没做过线段树维护剩余人数的,一时半会想不到...首先,我们要用打表找到所有点数。然后用线段树维护剩余人数,这里有一个剩余人数位置和所有人数位置转换的过程,是用线段树解决的。线段树的每个节点储存的是某个区间的剩余人数,所以我们在用一个人在剩余人中的位置找到他的编号时,是比较sum节点而非L,R。还有向左向右方向要注意,画个圈慢慢感受。具体看注释。

代码:

#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define ll long long
const int maxn = 500000+5;
const int MOD = 1e7;
const int INF = 0x3f3f3f3f;
using namespace std;
struct node{
char name[12];
int num;
}e[maxn];
int get[maxn],sum[maxn << 2];
void pushup(int rt){
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void build(int l,int r,int rt){
if(l == r){
sum[rt] = 1;
return;
}
int m = (l + r) >> 1;
build(l,m,rt << 1);
build(m + 1,r,rt << 1 | 1);
pushup(rt);
}
int update(int pos,int l,int r,int rt){
if(l == r){
sum[rt] = 0;
return l;
}
int ans;
int m = (l + r) >> 1;
if(pos <= sum[rt << 1]) //pos代表在剩余人数中的第几个,所以写法略有不同
ans = update(pos,l,m,rt << 1);
else
ans = update(pos - sum[rt << 1],m + 1,r,rt << 1 | 1);
pushup(rt);
return ans;
}
void init(){
int top = 500000;
memset(get,0,sizeof(get));
for(int i = 1;i <= top;i++){
get[i]++;
for(int j = 2*i;j <= top;j += i){
get[j]++;
}
}
}
int main(){
init();
int n,k;
while(~scanf("%d%d",&n,&k)){
build(1,n,1);
for(int i = 1;i <= n;i++)
scanf("%s%d",e[i].name,&e[i].num);
int aim = 0,MAX = -1;
for(int i = 1;i <= n;i++){
if(get[i] > MAX){
aim = i;
MAX = get[i];
}
}
int pos; //开始计算的位置
int mov,all,now = 0;
while(true){
pos = update(k,1,n,1); //被宰的是哪个人
now++;
if(now == aim) break;
mov = e[pos].num;
if(mov > 0){ //在左边
k = (k - 1 + mov - 1)%sum[1] + 1; //这里的pos是剩余人中的编号
//第一个-1是因为pos这个人已经被宰了,所以他这个位置其实是没有的
//第二个-1是防止%之后归0,所以先-1再+1
}
else{ //在右边
k = ((k - 1 + mov)%sum[1] + sum[1])%sum[1] + 1;
}
}
printf("%s %d\n",e[pos].name,MAX);
}
return 0;
}

POJ 2886 Who Gets the Most Candies? (线段树)题解的更多相关文章

  1. POJ 2886.Who Gets the Most Candies? -线段树(单点更新、类约瑟夫问题)

    线段树可真有意思呢续集2... 区间成段的替换和增减,以及区间求和等,其中夹杂着一些神奇的操作,数据离散化,简单hash,区间异或,还需要带着脑子来写题. 有的题目对数据的操作并不是直接按照题面意思进 ...

  2. POJ 2886 Who Gets the Most Candies?(线段树&#183;约瑟夫环)

    题意  n个人顺时针围成一圈玩约瑟夫游戏  每一个人手上有一个数val[i]   開始第k个人出队  若val[k] < 0 下一个出队的为在剩余的人中向右数 -val[k]个人   val[k ...

  3. POJ 2886 Who Gets the Most Candies? 线段树。。还有方向感

    这道题不仅仅是在考察线段树,还他妹的在考察一个人的方向感.... 和线段树有关的那几个函数写了一遍就对了,连改都没改,一直在转圈的问题的出错.... 题意:从第K个同学开始,若K的数字为正 则往右转, ...

  4. POJ 2886 Who Gets the Most Candies? 线段树

    题目: http://poj.org/problem?id=2886 左右转的果断晕,题目不难,关键是准确的转啊转.因为题目要求输出约数个数最多的数,所以预处理[1,500000]的约数的个数就行了. ...

  5. poj 2886 "Who Gets The Most Candies?"(树状数组)

    传送门 参考资料: [1]:http://www.hankcs.com/program/algorithm/poj-2886-who-gets-the-most-candies.html 题意: 抢糖 ...

  6. poj 3468 A Simple Problem with Integers 线段树 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=3468 线段树模板 要背下此模板 线段树 #include <iostream> #include <vector> ...

  7. 线段树(单点更新) POJ 2886 Who Gets the Most Candies?

    题目传送门 #include <cstdio> #include <cstring> #define lson l, m, rt << 1 #define rson ...

  8. POJ 2828 Buy Tickets(排队问题,线段树应用)

    POJ 2828 Buy Tickets(排队问题,线段树应用) ACM 题目地址:POJ 2828 Buy Tickets 题意:  排队买票时候插队.  给出一些数对,分别代表某个人的想要插入的位 ...

  9. POJ 2886 Who Gets the Most Candies? (线段树)

    [题目链接] http://poj.org/problem?id=2886 [题目大意] 一些人站成一个圈,每个人手上都有一个数字, 指定从一个人开始淘汰,每次一个人淘汰时,将手心里写着的数字x展示 ...

  10. (中等) POJ 2886 Who Gets the Most Candies? , 反素数+线段树。

    Description N children are sitting in a circle to play a game. The children are numbered from 1 to N ...

随机推荐

  1. LeetCode——Lowest Common Ancestor of a Binary Search Tree

    Description: Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given no ...

  2. IPMI相关漏洞利用及WEB端默认口令登录漏洞

    IPMI相关漏洞 0套件漏洞 使用0套件时,只需要Username,口令任意即可绕过身份鉴别执行指令.而且一般还有一个默认的账户admin或者ADMIN. 备注:IPMI是一套主机远程管理系统,可以远 ...

  3. 正则表达式—RegEx(RegularExpressio)(一)

    今日随笔,想和大家分享一下正则表达式的相关知识. 先不说概念性的东西,举一个例子再说. 验证你输入的邮政编码 ,你输入的邮政编码必须是六位的数字. while (true) { Console.Wri ...

  4. 微信小程序 --- 获取设备信息

    获取设备信息: wx.getSystemInfo model:手机型号 pixelRatio:设备像素比 windowWidth:窗口宽度 windowHeight:窗口高度 language:语言 ...

  5. Java 泛型 详解

    一.什么是泛型 本质而言,泛型指的是参数化的类型.参数化的类型的重要性是:它能让你创建类.接口和方法,由它们操作的数据类型被指定为一个参数.操作参数化类型的类.接口或方法被称为泛型,如泛型类或泛型方法 ...

  6. talib 中文文档(十五):Math Operator Functions 数学方法

    Math Operator Functions 数学运算符函数 ADD - Vector Arithmetic Add 函数名:ADD 名称:向量加法运算 real = ADD(high, low) ...

  7. 过山车---hdu2063(最大匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063最大匹配模板题: #include <iostream> #include <c ...

  8. yii2框架(一)安装

    手动安装下载yii2basic出现以下错误 2 修改 G:\learn\yii-basic-app-2.0.11\basic\config下web.conf 为cookieValidationKey设 ...

  9. Day07 jdk5.0新特性&Junit&反射

    day07总结 今日内容 MyEclipse安装与使用 JUnit使用 泛型 1.5新特性 自动装箱拆箱 增强for 静态导入 可变参数方法 枚举 反射 MyEclipse安装与使用(yes) 安装M ...

  10. oracle(十二)redo 与 undo

    1.undo:回滚未提交的事务.未提交前,内存不够用时,DBWR将脏数据写入数据文件中,以腾出内存空间. 这就是undo存在的原因. redo:恢复所有已提交的事务 2.实例失败(如主机掉电)可能出现 ...