题目链接

问题分析

参照数据范围,我们需要一个能够在\(O(n\log n)\)复杂度内维护有序数列的数据结构。那么平衡树是很好的选择。参考程序中使用带旋Treap。

参考程序

#pragma GCC optimize( 3 )
#include <cstdio>
#include <ctime>
#include <algorithm> namespace Treap {
struct member {
int Number, Time;
bool operator > ( const member Other ) const {
return Number < Other.Number || Number == Other.Number && Time > Other.Time;
};
bool operator == ( const member Other ) const {
return Number == Other.Number && Time == Other.Time;
};
bool operator < ( const member Other ) const {
return Number > Other.Number || Number == Other.Number && Time < Other.Time;
}
};
struct node {
int Random, Size, Cnt;
member Value;
node *LeftChild, *RightChild;
};
void Collect( node *A ) {
A->Size = A->Cnt + ( ( A->LeftChild != NULL ) ? A->LeftChild->Size : 0 ) + ( ( A->RightChild != NULL ) ? A->RightChild->Size : 0 );
return;
}
node *LeftRotate( node *A ) {
node *B = A->RightChild; A->RightChild = B->LeftChild; B->LeftChild = A; Collect( A ); Collect( B ); return B;
}
node *RightRotate( node *A ) {
node *B = A->LeftChild; A->LeftChild = B->RightChild; B->RightChild = A; Collect( A ); Collect( B ); return B;
}
node *Insert( node *Rt, member x ) {
if( Rt == NULL ) {
Rt = new node;
Rt->Random = rand() % 1000000000; Rt->Value = x; Rt->Size = 1; Rt->Cnt = 1; Rt->LeftChild = Rt->RightChild = NULL;
return Rt;
}
++( Rt->Size );
if( Rt->Value == x ) { ++( Rt->Cnt ); return Rt; }
if( Rt->Value < x ) {
Rt->RightChild = Insert( Rt->RightChild, x ); if( Rt->RightChild->Random < Rt->Random ) Rt = LeftRotate( Rt );
} else {
Rt->LeftChild = Insert( Rt->LeftChild, x ); if( Rt->LeftChild->Random < Rt->Random ) Rt = RightRotate( Rt );
}
return Rt;
}
node *Del( node *Rt, member x ) {
if( Rt == NULL ) { printf( "No such number called %d\n", x ); return Rt; }
if( Rt->Value == x ) {
if( Rt->Cnt > 1 ) { --( Rt->Cnt ); --( Rt->Size ); return Rt; }
if( Rt->LeftChild == NULL ) { node *T = Rt->RightChild; delete Rt; return T; }
if( Rt->RightChild == NULL ) { node *T = Rt->LeftChild; delete Rt; return T; }
if( Rt->LeftChild->Random <= Rt->RightChild->Random ) {
Rt = RightRotate( Rt ); --( Rt->Size ); Rt->RightChild = Del( Rt->RightChild, x ); return Rt;
} else {
Rt = LeftRotate( Rt ); --( Rt->Size ); Rt->LeftChild = Del( Rt->LeftChild, x ); return Rt;
}
return Rt;
}
--( Rt->Size );
if( Rt->Value < x ) { Rt->RightChild = Del( Rt->RightChild, x ); return Rt; }
else { Rt->LeftChild = Del( Rt->LeftChild, x ); return Rt; }
return Rt;
}
int QueryR( node *Rt, member x ) {
int Ans = 0;
for( ; Rt != NULL; ) {
if( Rt->Value == x ) return Ans + ( ( Rt->LeftChild != NULL ) ? Rt->LeftChild->Size : 0 ) + 1;
if( Rt->Value < x ) {
Ans += ( ( Rt->LeftChild != NULL ) ? Rt->LeftChild->Size : 0 ) + Rt->Cnt;
Rt = Rt->RightChild;
} else Rt = Rt->LeftChild;
}
return Ans + 1;
}
member QueryN( node *Rt, int x ) {
for( ; Rt != NULL; ) {
int Rc = 0; if( Rt->LeftChild != NULL ) Rc = Rt->LeftChild->Size;
if( x > Rc && x <= Rc + Rt->Cnt ) return Rt->Value;
if( x <= Rc ) Rt = Rt->LeftChild; else { x -= Rc + Rt->Cnt; Rt = Rt->RightChild; }
}
printf( "QueryNumber Failed.\n" );
return ( member ){ -1, -1 };
}
member pre( node *Rt, member x ) {
member Ans = x;
for( ; Rt != NULL; ) if( Rt->Value < x ) { Ans = Rt->Value; Rt = Rt->RightChild; } else Rt = Rt -> LeftChild;
if( Ans == x ) printf( "Query Pre Failed.\n" );
return Ans;
}
member suc( node *Rt, member x ) {
member Ans = x;
for( ; Rt != NULL; ) if( Rt->Value > x ) { Ans = Rt->Value; Rt = Rt->LeftChild; } else Rt = Rt -> RightChild;
if( Ans == x ) printf( "Query Suc Failed.\n" );
return Ans;
}
struct treap {
node *Root;
void clear() { delete [] Root; Root = NULL; srand( time( NULL ) ); return; }
void insert( member x ) { Root = Insert( Root, x ); return; }
void Delete( member x ) { Root = Del( Root, x ); return; }
int QueryRank( member x ) { return QueryR( Root, x ); }
member QueryNumber( int x ) { return QueryN( Root, x ); }
member Pre( member x ) { return pre( Root, x ); }
member Suc( member x ) { return suc( Root, x ); }
};
} //Treap Treap::treap Tree; namespace UI {
typedef unsigned int ui ;
ui randNum( ui& seed , ui last , const ui m){
seed = seed * 17 + last ; return seed % m + 1;
}
ui seed, last = 7;
void InSeed() { scanf( "%llu", &seed ); return; }
} //UI const int Maxm = 100010;
Treap::member Rec[ Maxm ]; void MAIN() {
Tree.clear();
int n, m; scanf( "%d%d", &m, &n ); UI::InSeed();
for( int i = 1; i <= m; ++i ) {
Tree.insert( ( Treap::member ){ 0, 0 } );
Rec[ i ] = ( Treap::member ){ 0, 0 };
}
for( int i = 1; i <= n; ++i ) {
int x = UI::randNum( UI::seed, UI::last, m );
int y = UI::randNum( UI::seed, UI::last, m );
Tree.Delete( Rec[ x ] );
++Rec[ x ].Number;
Rec[ x ].Time += y;
Tree.insert( Rec[ x ] );
UI::last = Tree.QueryRank( Rec[ x ] ) - 1;
printf( "%llu\n", UI::last );
}
return;
} int main() {
int TestCases; scanf( "%d", &TestCases );
for( ; TestCases--; ) MAIN();
return 0;
}

「TJOI2019」甲苯先生的滚榜的更多相关文章

  1. LG5338/BZOJ5509/LOJ3105 「TJOI2019」甲苯先生的滚榜 Treap

    问题描述 LG5338 LOJ3105 BZOJ5509 题解 建立一棵\(\mathrm{Treap}\),把原来的\(val\)换成两个值\(ac,tim\) 原来的比较\(val_a<va ...

  2. 【LOJ】#3109. 「TJOI2019」甲苯先生的线段树

    LOJ#3109. 「TJOI2019」甲苯先生的线段树 发现如果枚举路径两边的长度的话,如果根节点的值是$x$,左边走了$l$,右边走了$r$ 肯定答案会是$(2^{l + 1} + 2^{r + ...

  3. LOJ#3104「TJOI2019」甲苯先生的字符串

    题目描述 一天小甲苯得到了一条神的指示,他要把神的指示写下来,但是又不能泄露天机,所以他要用一种方法把神的指示记下来. 神的指示是一个字符串,记为字符串 \(s_1\),\(s_1\) 仅包含小写字母 ...

  4. LG5337/BZOJ5508 「TJOI2019」甲苯先生的字符串 线性动态规划+矩阵加速

    问题描述 LG5337 BZOJ5508 题解 设\(opt_{i,j}(i \in [1,n],j \in [1,26])\)代表区间\([1,i]\),结尾为\(j\)的写法. 设\(exist_ ...

  5. [TJOI2019]甲苯先生的滚榜——非旋转treap

    题目链接: [TJOI2019]甲苯先生的滚榜 要求维护一个二维权值的集合并支持单点修改,用平衡树维护即可. 因为$n\le 10^6$但$m\le 10^5$,所以最多只有$10^5$个人被操作. ...

  6. 洛谷P5338 [TJOI2019]甲苯先生的滚榜

    原题链接洛谷P5338 [TJOI2019]甲苯先生的滚榜 题目描述 甲苯先生在制作一个online judge,他发现做比赛的人们很关心自己的排名(显而易见),在acm赛制的比赛中,如果通过题目数量 ...

  7. BZOJ5509: [Tjoi2019]甲苯先生的滚榜

    题解 开n个平衡树对每个AC数维护罚时,然后不同AC数用树状数组维护即可. 其实挺好写的...就是评测的时候评的巨久... #include <bits/stdc++.h> using n ...

  8. 【题解】Luogu P5338 [TJOI2019]甲苯先生的滚榜

    原题传送门 这题明显可以平衡树直接大力整,所以我要说一下线段树+树状数组的做法 实际线段树+树状数组的做法也很暴力 我们先用树状数组维护每个ac数量有多少个队伍.这样就能快速求出有多少队伍ac数比现在 ...

  9. luogu P5338 [TJOI2019]甲苯先生的滚榜

    传送门 首先,排名系统,一看就知道是原题,可以上平衡树来维护 然后考虑一种比较朴素的想法,因为我们要知道排名在一个人前面的人数,也就是AC数比他多的人数+AC数一样并且罚时少的人数,所以考虑维护那两个 ...

随机推荐

  1. 面试40-一个数组,有2个数字出现奇数次,其余都是偶数次,求这两个数字O(n) O(1)

    #include<iostream> using namespace std; // 题目:数组中只有不多于两个数字出现次数是奇数次,其他都是偶数次,求出出现奇数次的数字(不含0的数组) ...

  2. thinkPHP验证码报错: Call to undefined function captcha_src()

    问题出现的原因可能有: 1. captcha扩展缺失: 2. captcha扩展与当前thinkPHP版本不兼容. thinkPHP6.0以下版本只能使用 captcha2.0以下版本,不支持2.0版 ...

  3. thinkphp5.1 关于加载静态资源路径问题

    和thinkphp5.0不一样,thinkphp5.1的 thinkphp5.0的 直接在config.php文件中加入代码: <?phpreturn [ 'view_replace_str' ...

  4. python面向对象反射-框架原理-动态导入-元类-自定义类-单例模式-项目的生命周期-05

    反射 reflect 反射(reflect)其实是反省,自省的意思 反省:指的是一个对象应该具备可以检测.修改.增加自身属性的能力 反射:通过字符串获取对象或者类的属性,进行操作 设计框架时需要通过反 ...

  5. Git服务器搭建与配置管理

    Git for Windows TortoiseGit:是一个开放的git版本控制系统的源客户端,支持Winxp/vista/win7.离不开真正的Git(Git for windows版本名字又叫M ...

  6. luogu P4755 Beautiful Pair

    luogu 这题有坨区间最大值,考虑最值分治.分治时每次取出最大值,然后考虑统计跨过这个位置的区间答案,然后两边递归处理.如果之枚举左端点,因为最大值确定,右端点权值要满足\(a_r\le \frac ...

  7. Dubbo从入门到实战视频教程

    Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成.这里整理了一套关于dubbo的视频教程分享给大家,包 ...

  8. Django框架——进阶之AJAX

    <script>$("#b1").on("click", function () { // 点击 id是b1的按钮要做的事儿 var i1 = $( ...

  9. laravel swoole Call to undefined method Illuminate\Events\Dispatcher::fire()

    报错: Call to undefined method Illuminate\Events\Dispatcher::fire() Whoops\Run::handleError("Unca ...

  10. c++的并发操作(多线程)

    C++11标准在标准库中为多线程提供了组件,这意味着使用C++编写与平台无关的多线程程序成为可能,而C++程序的可移植性也得到了有力的保证.另外,并发编程可提高应用的性能,这对对性能锱铢必较的C++程 ...