Who Gets the Most Candies? POJ - 2886(线段树单点更新+区间查询+反素数)
预备知识:反素数解析
思路:有了反素数的解法之后就是线段树的事了。
我们可以用线段树来维护哪些人被淘汰,哪些人没被淘汰,被淘汰的人的位置,没被淘汰的人的位置。
我们可以把所有人表示为一个[1,n]的区间,没被淘汰的人权值为1,那么通过线段树维护区间和,就可以知道没被淘汰人的分布情况,tree[root].value就是总人数。因为线段树的二分性质,如果淘汰的人在第x个位置,那么我们可以找到区间和为x的位置来得到这个人的位置,把这个位置的权值更新为0,然后更新线段树,就可以表示这个人被淘汰,总人数也是减去1,就可以表示游戏中还剩多少人。
假设这个被淘汰的人位置是inx,下一个淘汰的人位于他的左(右)第A个,我们可以mod = A%(剩余人数),然后我们可以得到inx左边(L)和右边的人数(R),然后根据mod和A的正负号来确定下一个人的位置。
#include <iostream>
#include <cmath>
#include <cstdio> #define ll long long using namespace std; const int N = 5e5+;
struct Info{
char name[];
int turn;
}p[N];
struct node{
int l,r,value;
int mid(){ return (l+r) >> ; }
}tree[N << ];
int c[N];
int n, s, ss, inx;
int pr[] = {,,,,,,,,,};
int Max,num; void dfs(int inx, int v, int cnt, int pw){
for(int i = ; i <= pw; ++i){
if((ll)v * pr[inx] > (ll)n){
if(Max < cnt * i){
Max = cnt * i;
num = v; }else if(cnt * i == Max) num = min(num, v);
break;
}
else dfs(inx + , v *= pr[inx], cnt * (i + ), i); }
} //反素数模板
void AntPrime(){
Max = ;
dfs(, , , );
} void build_tree(int rt, int L, int R){
tree[rt].l = L; tree[rt].r = R;
if(L == R){
if(L == s) inx = rt;
tree[rt].value = ;
return;
}
int mid = tree[rt].mid();
int lson = rt << ;
int rson = rt << | ;
build_tree(lson, L, mid);
build_tree(rson,mid + , R);
tree[rt].value = tree[lson].value + tree[rson].value;
} void update(int x){
while(x != ){
--tree[x].value;
x >>= ;
}
} void search(int tot,int rt){
//找到位置
if(tree[rt].l == tree[rt].r){
ss = tree[rt].l; //原始队列的位置
inx = rt; //线段树的位置,方便更新
return;
}
int lson = rt << ;
int rson = rt << | ;
if(tree[lson].value >= tot) search(tot, lson);
else search(tot - tree[lson].value, rson);
} void solve(){
while(~scanf("%d%d", &n, &s)){
build_tree(,,n);
AntPrime();//得到反素数和它的约数个数
for(int i = ; i <= n; ++i){
scanf("%s%d", p[i].name, &p[i].turn);
}
int cnt = ;
int remain = n;
//s 淘汰队列人的位置
//ss 原始队列人的位置
ss = s;
while(++cnt != num){
update(inx);//更新线段树
int turn = abs((double)p[ss].turn);
turn %= (remain - );
if(!turn) turn = remain - ;
if(p[ss].turn > ){
int r = remain - s;
if(r >= turn) s = s + turn - ;
else s = turn - r;
}else{
int l = s - ;
if(l >= turn) s = l - turn + ;
else s = (remain - ) - (turn - l) + ;
}
// cout << "position is " << ss << endl;
// cout << "jumped out people " << p[ss].name << endl;
search(s, );
--remain;
}
printf("%s %d\n", p[ss].name, Max);
}
} int main(){ solve(); return ;
}
Who Gets the Most Candies? POJ - 2886(线段树单点更新+区间查询+反素数)的更多相关文章
- POJ 2886 线段树单点更新
转载自:http://blog.csdn.net/sdj222555/article/details/6878651 反素数拓展参照:http://blog.csdn.net/ACdreamers/a ...
- HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)
HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...
- NYOJ-568/1012//UVA-12299RMQ with Shifts,线段树单点更新+区间查询
RMQ with Shifts 时间限制:1000 ms | 内存限制:65535 KB 难度:3 -> Link1 <- -> Link2 <- 以上两题题意是一样 ...
- poj 2886 线段树的更新+反素数
Who Gets the Most Candies? Time Limit: 5000 MS Memory Limit: 0 KB 64-bit integer IO format: %I64d , ...
- poj 2828(线段树单点更新)
Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 18561 Accepted: 9209 Desc ...
- POJ 2828 (线段树 单点更新) Buy Tickets
倒着插,倒着插,这道题是倒着插! 想一下如果 Posi 里面有若干个0,那么排在最前面的一定是最后一个0. 从后往前看,对于第i个数,就应该插在第Posi + 1个空位上,所以用线段树来维护区间空位的 ...
- HDU 1166敌兵布阵+NOJv2 1025: Hkhv love spent money(线段树单点更新区间查询)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU1166(线段树单点更新区间查询)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU 1754.I Hate It-结构体版线段树(单点更新+区间查询最值)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
随机推荐
- 吴裕雄--天生自然 R语言开发学习:时间序列(续一)
#-----------------------------------------# # R in Action (2nd ed): Chapter 15 # # Time series # # r ...
- 吴裕雄--天生自然 R语言开发学习:功效分析
#----------------------------------------# # R in Action (2nd ed): Chapter 10 # # Power analysis # # ...
- webstorm active code
6ZUMD7WWWU-eyJsaWNlbnNlSWQiOiI2WlVNRDdXV1dVIiwibGljZW5zZWVOYW1lIjoiSmV0cyBHcm91cCIsImFzc2lnbmVlTmFtZ ...
- 【转载】python3安装scrapy之windows32位爬坑
python3安装scrapy之windows32位爬坑 原创 2016年11月06日 01:38:08 标签: scrapy / windows / python / 开源框架 / 网络爬虫 早 ...
- 仿豆瓣首页弹性滑动控件|Axlchen's blog
逛豆瓣的时候看到了这样的控件,觉得挺有趣,遂模仿之 先看看原版的效果 再看看模仿的效果 分析 控件结构分析 由于*ScrollView只能有一个child view,所以整个child view的结构 ...
- usb设备枚举过程
USB主机在检测到USB设备插入后,就要对设备进行枚举了.为什么要枚举呢?枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序.调试USB设 ...
- 实用的Python(3)超简单!基于Python搭建个人“云盘”
1 简介 当我们想要从本地向云服务器上传文件时,比较常用的有pscp等工具,但避免不了每次上传都要写若干重复的代码,而笔者最近发现的一个基于Python的工具updog,可以帮助我们在服务器上搭建类似 ...
- 使用webpack从0搭建多入口网站脚手架,可复用导航栏/底部通栏/侧边栏,根据页面文件自动更改配置,支持ES6/Less
之前只知道webpack很强大,但是一直没有深入学习过,这次从头看了一下教程,然后从0开始搭建了一个多入口网站的开发脚手架,期间遇到过很多问题,所以有心整理一下,希望能给大家一点帮助. 多HTML网站 ...
- JavaScript常见的六种继承方式
前言 面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分面向对象的编程语言,都是通过"类 ...
- spring——AOP原理及源码(四)
前情回顾: 上文我们一路分析了从容器创建开始直到我们的AOP注解导入的核心组件AnnotationAwareAspectJAutoProxyCreator执行postProcessBeforeInst ...