预备知识:反素数解析

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

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

我们可以把所有人表示为一个[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 ;
}

最新文章

  1. 将复杂查询写到SQL配置文件--SOD框架的SQL-MAP技术简介
  2. Java初识
  3. CPU虚拟化技术(留坑)
  4. SQLite之写一个表
  5. UVa 12100 (模拟) Printer Queue
  6. Android Recovery的汉化 显示中文
  7. Centos安装后,没有ifconfig工具
  8. python写的一段分页的代码
  9. EasyUI中tree,Datagrid,pagenation的使用EasyUI中Datagrid和pagenation进行关联时,再次点击pagenation时让表格数据显示的问题
  10. sql server 多行数据合并成一列
  11. java代码之美(4)---guava之Immutable(不可变)集合
  12. LFYZ-OJ ID: 1024 火车站
  13. Docker 学习新手笔记:从入门到放弃
  14. 7_CentOS下安装和卸载AdobeReader
  15. java 基础 动态绑定和多态
  16. 原 HTML5 requestFullScreen&amp;exitFullscreen全屏兼容方案
  17. Geoserver+Postgresql+PostGIS 进行数据发布
  18. SQL&#160;跟据出生日期求年龄
  19. 《Linux设备驱动开发详解(第3版)》(即《Linux设备驱动开发详解:基于最新的Linux 4.0内核》)--宋宝华
  20. CENTOS6.5安装CDH5.12.1(一) https://mp.weixin.qq.com/s/AP_m0QqKgzEUfjf0PQCX-w

热门文章

  1. 常见40个常用的js页面效果图
  2. the way of hardware design study
  3. 通过zxing生成二维码
  4. 二十一世纪计算 | John Hopcroft:AI革命
  5. MySQL安装和常用命令
  6. 【基础篇】hexo博客搭建教程
  7. MySQL多表查询、事务、DCL:内含mysql如果忘记密码解决方案
  8. Samtec与Neoconix达成合作并和II-VI推出新产品
  9. 【11】openlayers 地图交互
  10. Java集合01——List 的几个实现类,了解一下?