首页 > 其他分享 >P8671 [蓝桥杯 2018 国 AC] 约瑟夫环 题解

P8671 [蓝桥杯 2018 国 AC] 约瑟夫环 题解

时间:2022-11-02 19:45:56浏览次数:91  
标签:pbds AC 树状 int 题解 tree 蓝桥 数组 mathcal

约瑟夫环有 \(\mathcal O(n)\) 做法相信大家都知道。这里就不在介绍了,这里给出一个不知道这个结论的 \(\mathcal O(n\log n)\) 简单做法。
考虑直接模拟题意,每次循环往后数 \(k\) 个然后把这个数给删掉,如果采用链表的话找 \(k\) 个是要超时的,考虑换个数据结构比如平衡树,支持 \(\mathcal O(\log n)\) 求排名,插入或删除。于是就打了个平衡树上去。

#include<ext/pb_ds/assoc_container.hpp>
namespace pbds=__gnu_pbds;
pbds::tree<int,pbds::null_type,std::less<>,pbds::rb_tree_tag,pbds::tree_order_statistics_node_update>s;
int n,k;
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	std::ios::sync_with_stdio(false);cin.tie(nullptr);
	cin>>n>>k;
	for(int i=1;i<=n;i++)s.insert(i);
	for(int i=1;--n;){
		i=(i+k-2)%(n+1)+1;
		s.erase(s.find_by_order(i-1));
	}
	cout<<*s.begin();
	return 0;
}

发现 pbds 的平衡树跑不过去,难道是太慢超时了?这该怎么办呢?众所周知基础平衡树的所有题都可以离线下来用树状数组去解决,那这里 find_by_order 这个操作就要用到树状数组上二分这个做法去实现。
代码:

constexpr int N=2e6+1;
int n,k;
struct{
	int d[N];
	void add(int x){for(;x<N;x+=x&-x)d[x]++;}
	void del(int x){for(;x<N;x+=x&-x)d[x]--;}
	int kth(int x){
		int p=1<<std::__lg(N);
		for(int i=std::__lg(N)-1;~i;i--)
			if(d[p-(1<<i)]>=x)p-=(1<<i);
			else x-=d[p-(1<<i)];
		return p;
	}
}s;
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	std::ios::sync_with_stdio(false);cin.tie(nullptr);
	cin>>n>>k;
	for(int i=1;i<=n;i++)s.add(i);
	for(int i=1;--n;){
		i=(i+k-2)%(n+1)+1;
		s.del(s.kth(i));
	}
	cout<<s.kth(1);
	return 0;
}

这里简单介绍一下树状数组上二分这个算法:先把当前位置调整成整个数组总和的位置(也就是 1..0000,这样才能保证 \([1,n]\) 都被 \(p\) 包含,为了方便,空间开两倍),从高位向低位考虑,如果左儿子比 \(k\) 大表示答案一定在左儿子,进入左儿子就行了,否则就在右儿子里面,把排名 \(k\) 减去左儿子的总和就行了。
CF1354D 这题也是采取树状数组去代替平衡树,也要用到树状数组上二分这个办法,可以去做一做。

标签:pbds,AC,树状,int,题解,tree,蓝桥,数组,mathcal
From: https://www.cnblogs.com/bxjz/p/P8671.html

相关文章

  • [题解]CF1327F
    首先拆位,然后考虑限制会带来什么。要求与起来是\(1\)的必须全是\(1\),差分打个标记。要求与起来是\(0\)的必须至少有一个\(0\),考虑如何计数。计数问题有可能是动态......
  • acwing298 围栏
    有 NN 块木板从左到右排成一行,有 MM 个工匠对这些木板进行粉刷,每块木板至多被粉刷一次。第 ii 个木匠要么不粉刷,要么粉刷包含木板 Si 的,长度不超过 Li 的连续的......
  • ACM预备队-week2(二分)
    STO#y总#Or2二分:check函数+两模板;(前提是已经排好序才能二分)假设有一个总区间,经由我们的check函数判断后,可分成两部分,这边以o作true,.....作false示意较好识别如果我......
  • 学习笔记-Aircrack
    Aircrack免责声明本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关.简介aircrack是一个比较出名的用于破解......
  • saltstack服务端与客户端通信问题处理
    jenkins发布报错:ERROR:NoreturnreceivedNominionsmatchedthetarget.Nocommandwassent,nojidwasassigned.saltstack分为服务端master与客户端minion配置文......
  • 为何传统的日志和可观测性会浪费开发人员的时间|TheNewStack
    【文章来源】https://thenewstack.io/why-traditional-logging-and-observability-waste-developer-time/左移(使数据位向左移动的移位操作)可观测性的神奇之处在于:能直接......
  • CF1729G Cut Substrings 题解
    CF1729GCutSubstrings给出两个字符串\(s,t\),每次可以将字符串\(s\)中任意一个为\(t\)的子串删除,删除位置的字符变为空格(或理解为无实义)。求最少删除几次可以使得......
  • Layabox2.4+webpack4.x打包编译、热更新
    在laya项目目录下新建package.json点击查看代码{"scripts":{"bundle:dev":"webpack--configwebpack.config.debug.js--watch","serve":......
  • TRACE_EVENT使用
    先上参考链接如何使用TRACE_EVENT()宏来创建跟踪点UsingtheTRACE_EVENT()macro这是自己总结的图最后是实操可能碰到的一些问题包含TRACE_EVENT()宏的头文件必须遵......
  • 'ascii' codec can't encode character u'\u2018'
    我是在学习Python的图像识别时遇到了这个问题,应该是中文语言包里面的不兼容问题,这个问题,说白了,还是Python的转码问题,各个编码之间的不兼容,解决办法:代码开头加入:......