预备知识:反素数解析

思路:有了反素数的解法之后就是线段树的事了。

我们可以用线段树来维护哪些人被淘汰,哪些人没被淘汰,被淘汰的人的位置,没被淘汰的人的位置。

我们可以把所有人表示为一个[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(线段树单点更新+区间查询+反素数)的更多相关文章

  1. POJ 2886 线段树单点更新

    转载自:http://blog.csdn.net/sdj222555/article/details/6878651 反素数拓展参照:http://blog.csdn.net/ACdreamers/a ...

  2. HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)

    HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...

  3. NYOJ-568/1012//UVA-12299RMQ with Shifts,线段树单点更新+区间查询

    RMQ with Shifts 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 ->  Link1  <- -> Link2  <- 以上两题题意是一样 ...

  4. poj 2886 线段树的更新+反素数

    Who Gets the Most Candies? Time Limit: 5000 MS Memory Limit: 0 KB 64-bit integer IO format: %I64d , ...

  5. poj 2828(线段树单点更新)

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 18561   Accepted: 9209 Desc ...

  6. POJ 2828 (线段树 单点更新) Buy Tickets

    倒着插,倒着插,这道题是倒着插! 想一下如果 Posi 里面有若干个0,那么排在最前面的一定是最后一个0. 从后往前看,对于第i个数,就应该插在第Posi + 1个空位上,所以用线段树来维护区间空位的 ...

  7. HDU 1166敌兵布阵+NOJv2 1025: Hkhv love spent money(线段树单点更新区间查询)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  8. HDU1166(线段树单点更新区间查询)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  9. HDU 1754.I Hate It-结构体版线段树(单点更新+区间查询最值)

    I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

随机推荐

  1. 分布式ID生成策略 · fossi

    分布式环境下如何保证ID的不重复呢?一般我们可能会想到用UUID来实现嘛.但是UUID一般可以获取当前时间的毫秒数再加点随机数,但是在高并发下仍然可能重复.最重要的是,如果我要用这种UUID来生成分表 ...

  2. 吴裕雄--天生自然 PHP开发学习:本地PHPSTORM在线连接、编辑、上传文件到虚拟机,并在本地浏览器运行(前提是虚拟机与本机已桥连成功)

  3. CoreGraphic

    public func UIGraphicsBeginImageContextWithOptions( size: CGSize, opaque: Bool, _ scale: CGFloat) si ...

  4. Java并发编程(01):线程的创建方式,状态周期管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.并发编程简介 1.基础概念 程序 与计算机系统操作有关的计算机程序.规程.规则,以及可能有的文件.文档及数据. 进程 进程是计算机中的程序 ...

  5. Asp.Net Core EndPoint 终点路由工作原理解读

    一.背景 在本打算写一篇关于Identityserver4 的文章时候,确发现自己对EndPoint -终结点路由还不是很了解,故暂时先放弃了IdentityServer4 的研究和编写:所以才产生了 ...

  6. 用nodejs+express搭建前端测试服务端

    平时开发前端应用,如果没有现成的后端接口调试,又要保证前端进度,该怎么办呢,当然办法还是很多的,很多大牛都分享过很多经验,我也来说说我常用的方法. 请求本地数据文件 把本地数据放到程序指定目录,发起h ...

  7. 前端实现html转pdf方法总结

    最近要搞前端html转pdf的功能.折腾了两天,略有所收,踩了一些坑,所以做些记录,为后来的兄弟做些提示,也算是回馈社区.经过一番调(sou)研(suo)发现html导出pdf一般有这几种方式,各有各 ...

  8. Nacos 数据持久化 mysql8.0

    一.问题描述 直接下载的稳定版本nacos编译后的文件,不支持mysql8及其以上版本,按照官网文档:https://nacos.io/zh-cn/docs/deployment.html 执行完成之 ...

  9. Python学习之布尔和数字

    布尔有True和Flase两种值 数字0.None,以及元素为空的容器类对象都可视为False,反之为Ture.

  10. Flink消费Kafka到HDFS实现及详解

    1.概述 最近有同学留言咨询,Flink消费Kafka的一些问题,今天笔者将用一个小案例来为大家介绍如何将Kafka中的数据,通过Flink任务来消费并存储到HDFS上. 2.内容 这里举个消费Kaf ...