传送门

参考资料:

  [1]:http://www.hankcs.com/program/algorithm/poj-2886-who-gets-the-most-candies.html

题意:

  抢糖:N个熊孩子围成一个圈,从第K个开始淘汰,每淘汰一个,出示手中的数字,决定下一个淘汰者,正数表示左手第n个,负数反之。每个人可以拿到的存活回数的因数个数的糖果,求拿到最多糖果数的孩子的名字以及糖果数。

  (以上题意来自参考资料[1])

下面谈谈我对参考资料[1]的理解:

  下面介绍一下相对位置的概念(自己理解的,表达欠缺还请留言告知):

  假设初始有 6 个人,编号分别为 1~6

  1  2  3  4  5  6(初始编号)

  1  2  3  4  5  6(相对位置)

  初始编号为2的小盆友离开后,相对位置变为:

  1  3  4  5  6(初始编号)

  1  2  3  4  5(相对位置)

  那么,首先考虑这个问题,如何根据当前离开的小盆友的初始编号 k 和其手中的卡片 x 确定下一个小盆友离开的相对位置?

  分两种情况:

  假设当前还有 curTot 个小盆友,k 位置前有 before 个小盆友,k 位置后有 after 个小盆友(before + after = curTot);

  ① x > 0

    从 k 位置向右找第 x 个小盆友,相当于从第一个位置的小盆友向右找第 nex=(before+x)%curTot 个小盆友;

    因为第一个小盆友的相对位置为 1,所以,需要查找的第 nex 个小盆友的相对位置为 nex+1;

  ② x < 0

    从第 k 位置向左找第 x 个小盆友,相当于从第一个位置的小盆友向左找第 nex=(after+x)%curTot 个小盆友;

    当前一共有 curTot 个小盆友,那,相当于从第一个位置的小盆友向右找第 nex= (curTot-nex)%curTot 个小盆友;

    因为第一个小盆友的相对位置为 1,所以,需要查找的第 nex 个小盆友的相对位置为 nex+1;

  相对位置求出来后,如何求解其对应的初始编号呢???

  引用参考资料[1]博主的话就是 “这种区域修改可以活用BIT高效完成”;

  怎么个活用法呢?

  首先看一下BIT代码:

 struct BIT
{
int bit[maxn];
void Init()
{
mem(bit,);
}
void Add(int t,int x)
{
while(t < maxn)
{
bit[t] += x;
t += lowbit(t);
}
}
int Sum(int t)
{
int sum=;
while(t > )
{
sum += bit[t];
t -= lowbit(t);
}
return sum;
}
}_bit;

  初始,将 1~n 个小盆友全加入到BIT中;

for(int i=;i <= n;++i)
_bit.Add(i,);

  那么,此时初始编号 i 对应的前缀和Sum(i)正好为 i 的相对位置:

          i : 1  2  3  4  5  6

  _bit.Sum(i) : 1  2  3  4  5  6

  假设初始 i = 2 小盆友出队,调用_bit.Add(2,-1)

          i : 1  2  3  4  5  6

  _bit.Sum(i) : 1  1  2  3  3  4

  如果我现在想知道相对位置为3的小盆友的初始编号,该怎么办呢?

  你会发现,_bit.Sum(4) = 3,4正好是2好小盆友出队后相对位置为3的小盆友的编号;

  那么,想要找相对位置为 pos 的初始编号,只需在_bit.Sum()中找第一个使 _bit.Sun(No) = pos 的No即可;

  因为 _bit.Sum() 有序,所以,在查找的时候可以二分查找以提高效率;

AC代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define lowbit(x) (x&-x)
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=5e5+; int n,k;
char name[maxn][];
int x[maxn];
int factor[maxn];
struct BIT
{
int bit[maxn];
void Init()
{
mem(bit,);
}
void Add(int t,int x)
{
while(t < maxn)
{
bit[t] += x;
t += lowbit(t);
}
}
int Sum(int t)
{
int sum=;
while(t > )
{
sum += bit[t];
t -= lowbit(t);
}
return sum;
}
int BS(int x)
{
int l=,r=n+;
while(r-l > )
{
int mid=l+((r-l)>>);
if(Sum(mid) >= x)
r=mid;
else
l=mid;
}
return r;//使Sum()=x 的第一个位置
}
}_bit;
void factorTable()
{
fill(factor,factor+maxn,);
for(int i=;i < maxn;++i)
{
if(factor[i] != )
continue;
for(int j=i;j <= maxn;j+=i)
{
int k=;
for(int m=j;m%i == ;m/=i,k++);
factor[j] *= k+;//j包含k个质数i
}
}
}
void Solve()
{
int candy=;
int index;
for(int i=;i <= n;++i)
{
if(candy < factor[i])
{
candy=factor[i];//更新candy
index=k;//第i个出队的编号是k(初始编号)
}
if(i == n)
break; _bit.Add(k,-);
int nex;
int curTot=n-i;//当前剩余小盆友的个数
if(x[k] > )//情况①
{
nex=(x[k]+_bit.Sum(k)-)%curTot;
nex++;
}
else//情况②
{
x[k]=-x[k];
nex=(x[k]+curTot-_bit.Sum(k))%curTot;//向左找第nex个
nex=(curTot-nex)%curTot;//转化为向右找
nex++;
}
k=_bit.BS(nex);//二分查找相对位置为nex的初始编号
}
printf("%s %d\n",name[index],candy);
}
int main()
{
factorTable();//预处理出因子表
while(~scanf("%d%d",&n,&k))
{
_bit.Init();
for(int i=;i <= n;++i)
{
scanf("%s%d",name[i],x+i);
_bit.Add(i,);
}
Solve();
}
return ;
}

其实,这道题被我搁置四天了,当时按照自己的思路写了个线段树的,wa了;

改了许久无果,无奈,搜了搜题解,第一个题解看的就是参考资料[1],

不过,当时没怎么理解,又找了找其他人的博客,学到了一个新概念--反素数(可以提前打出反素数表,也可以提前打出因子表);

这几天,训练赛几乎每天都有,忙着训练,忙着补题;

这道题只是在我闲暇时光看看,捋捋思路;

昨天晚上终于有点懵懂;

今天,又花费了一个多小时,终于AC了,不过,和[1]博主的代码不太一样,[1]博主的代码我还没怎么,理解透呢,只是有点懵懂;

或许,这就是大佬吧,写出的代码得让吾等蒟蒻看好久才能理解Orz

poj 2886 "Who Gets The Most Candies?"(树状数组)的更多相关文章

  1. POJ 2886 Who Gets the Most Candies?(树状数组+二分)

    题目链接 注意题目中给的顺序是顺时针的,所以在数组中应该是倒着存的.左就是顺时针,右就是逆时针.各种调试之后,终于A了,很多种情况考虑情况. #include <cstring> #inc ...

  2. poj 1195:Mobile phones(二维树状数组,矩阵求和)

    Mobile phones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 14489   Accepted: 6735 De ...

  3. POJ 2352 &amp;&amp; HDU 1541 Stars (树状数组)

    一開始想,总感觉是DP,但是最后什么都没想到.还暴力的交了一发. 然后開始写线段树,结果超时.感觉自己线段树的写法有问题.改天再写.先把树状数组的写法贴出来吧. ~~~~~~~~~~~~~~~~~~~ ...

  4. [poj 1533]最长上升子序列nlogn树状数组

    题目链接:http://poj.org/problem?id=2533 其实这个题的数据范围n^2都可以过,只是为了练习一下nlogn的写法. 最长上升子序列的nlogn写法有两种,一种是变形的dp, ...

  5. POJ 2985 The k-th Largest Group(树状数组 并查集/查找第k大的数)

    传送门 The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8690   Acce ...

  6. POJ 1195 Mobile phones(二维树状数组)

                                                                  Mobile phones Time Limit: 5000MS   Mem ...

  7. POJ 3321 Apple Tree(dfs序树状数组)

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=10486 题意:一颗有n个分支的苹果树,根为1,每个分支只有一个苹果,给出n- ...

  8. POJ 2892 Tunnel Warfare || HDU 1540(树状数组+二分 || 线段树的单点更新+区间查询)

    点我看题目 题意 :N个村子连成一条线,相邻的村子都有直接的地道进行相连,不相连的都由地道间接相连,三个命令,D x,表示x村庄被摧毁,R  ,表示最后被摧毁的村庄已经重建了,Q x表示,与x直接或间 ...

  9. 【POJ 3167】Cow Patterns (KMP+树状数组)

    Cow Patterns Description A particular subgroup of K (1 <= K <= 25,000) of Farmer John's cows l ...

  10. POJ 1195 Mobile phones (二维树状数组或线段树)

    偶然发现这题还没A掉............速速解决了............. 树状数组和线段树比较下,线段树是在是太冗余了,以后能用树状数组还是尽量用......... #include < ...

随机推荐

  1. 腾讯云申请SSL证书与Nginx配置Https

    0x00 为什么要安装证书 信息传输的保密性 数据交换的完整性 信息的不可否认性 交易者身份确定性 如今各大浏览器厂商不断推进Https安全访问强制性要求,为了避免以后网站数据量增多时安装证书造成不必 ...

  2. Flask技术问题汇总

    1:Flask 使用 request对象代理了当前请求的上下文.这么做什么好处和坏处? 好处:flask封装了C端发起request对象,这样就可以使用上下文临时把某些对象变为全局可访问:如果不封装, ...

  3. 共创力董事长杨学明先生受邀参加CED智慧大会!

    2018年11月14日, 深圳市共创力咨询董事长.深圳市汇成研发管理咨询公司董事长杨学明先生受邀参加由深圳图书馆主办,深圳手讯视频承办的“倾听行业之声”2018第二届世界CED智慧大会,此次分享的主题 ...

  4. 测者的测试技术手册:自动化的自动化EvoSuite:Maven项目集成EvoSuite实战

    EvoSuite是由Sheffield等大学联合开发的一种开源工具,用于自动生成测试用例集,生成的测试用例均符合Junit的标准,可直接在Junit中运行.得到了Google和Yourkit的支持. ...

  5. 周一02.3运行python程序的两种方式

    一.运行python程序的两种方式 方法一:交互式:                     优点:输入一行代码立刻返回结果                      缺点:无法永久保存代码 方法二: ...

  6. windows server 几大实时同步软件比较

    需求: 从Windows Server 主机A 到 Windows Server 主机B 之间同步目录 方案一: 1. 使用bat脚本 + 计划任务的方式 1.1 bat脚本 功能: 把主机A的C:\ ...

  7. GDB调试指南-变量查看

    前言 在启动调试以及设置断点之后,就到了我们非常关键的一步-查看变量.GDB调试最大的目的之一就是走查代码,查看运行结果是否符合预期.既然如此,我们就不得不了解一些查看各种类型变量的方法,以帮助我们进 ...

  8. ztree 为节点添加点击触发事件

    <SCRIPT type="text/javascript"> var setting = { data : { key : { title : "code& ...

  9. nginx正则匹配

    1.通用匹配规则 .     匹配除换行符以外的任意字符 \w  匹配字母.数字.下划线.汉字 \s   匹配任意的空白符 \d   匹配数字 ^    匹配字符串的开始 $    匹配字符串的结束 ...

  10. IDEA快捷建使用

    因为以前使用的IDE工具是Eclipse,所以在公司中都是用IDEA的情况下,换成了IDEA,感觉是好用了很多. 其他快捷键: Ctrl+Shift + Enter,语句完成 “!”,否定完成,输入表 ...