POJ 2886 Who Gets the Most Candies? (线段树)题解
题意:一堆小朋友围成一个圈,规定从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? (线段树)题解的更多相关文章
- 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 2886 Who Gets the Most Candies? 线段树
题目: http://poj.org/problem?id=2886 左右转的果断晕,题目不难,关键是准确的转啊转.因为题目要求输出约数个数最多的数,所以预处理[1,500000]的约数的个数就行了. ...
- poj 2886 "Who Gets The Most Candies?"(树状数组)
传送门 参考资料: [1]:http://www.hankcs.com/program/algorithm/poj-2886-who-gets-the-most-candies.html 题意: 抢糖 ...
- poj 3468 A Simple Problem with Integers 线段树 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=3468 线段树模板 要背下此模板 线段树 #include <iostream> #include <vector> ...
- 线段树(单点更新) POJ 2886 Who Gets the Most Candies?
题目传送门 #include <cstdio> #include <cstring> #define lson l, m, rt << 1 #define rson ...
- POJ 2828 Buy Tickets(排队问题,线段树应用)
POJ 2828 Buy Tickets(排队问题,线段树应用) ACM 题目地址:POJ 2828 Buy Tickets 题意: 排队买票时候插队. 给出一些数对,分别代表某个人的想要插入的位 ...
- POJ 2886 Who Gets the Most Candies? (线段树)
[题目链接] http://poj.org/problem?id=2886 [题目大意] 一些人站成一个圈,每个人手上都有一个数字, 指定从一个人开始淘汰,每次一个人淘汰时,将手心里写着的数字x展示 ...
- (中等) 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 ...
随机推荐
- LeetCode——Basic Calculator
Description: Implement a basic calculator to evaluate a simple expression string. The expression str ...
- linux设置安全连接设置(私钥)
1.私钥制作工具:puttygen 连接工具:xshell和putty. 2.制作私钥和公钥 a.打开puttygen点击Generate生产公钥和私钥(鼠标需要晃动,进度条才会前进) b. 设置标签 ...
- ROM和RAM的故事
在公众号里看到一篇很好的文章讲解rom和ram,之前也是一直不能理解两者的区别,今天就转载记下来吧.也方便大家学习. 因为我刚开始学习的时候总喜欢刨根问底,一个问题要是不搞清楚,后面学习都会很吃力的. ...
- 树链剖分-点的分治(dis[i]+dis[j]==k的点对数量)
poj2114 Boatherds Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 1195 Accepted: 387 ...
- 170628、springboot编程之Druid数据源和监控配置一
Spring Boot默认的数据源是:org.apache.tomcat.jdbc.pool.DataSource,那么如何修改数据源呢?我已目前使用比较多的阿里数据源Druid为例,如果使用其他的数 ...
- scrapy爬虫系列之三--爬取图片保存到本地
功能点:如何爬取图片,并保存到本地 爬取网站:斗鱼主播 完整代码:https://files.cnblogs.com/files/bookwed/Douyu.zip 主要代码: douyu.py im ...
- Qt 控制线程的顺序执行(使用QWaitCondition,并且线程类的run函数里记得加exec(),使得线程常驻)
背景项目中用到多线程,对线程的执行顺序有要求: A.一个线程先收数据 B.一个线程处理数据 C.一个线程再将处理后的数据发送出去 要求三个线程按照ABC的顺序循环执行. 思路子类化多线程方法 重写子类 ...
- D. Little Artem and Dance---cf669D(模拟)
题目链接:http://codeforces.com/problemset/problem/669/D 给你n个数,一开始是1 2 3 4 5 6 ... n 这样的 现在有两个操作,第一个操作是所有 ...
- 11.Git分支管理
分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN. 如果两个平行宇宙互不干扰,那对现在的你也没啥影响.不过,在某个时间点,两个平行宇宙合并 ...
- 【手机自动化测试】monkey测试
1 概述 Monkey测试是Android自动化测试的一种手段.Monkey测试本身非常简单,就是模拟用户的按键输入,触摸屏输入,手势输入等,看设备多长时间会出异常. 当Mon ...