予備知識:抗分析プライムの数
アイデア:ソリューションで抗素数後は、セグメントツリーの事です。
除去することができ、誰が解消されていない私たちは、木のメンテナンスの位置でラインを出していなかった人の位置を排除しました。
私たちは[1、n]の範囲のように表現皆を置くことができ、人権が解消されていない1で、その後、メンテナンス間隔と木のラインで、それを排除することはできませんが、人の分布を知って、ツリー[ルート] .VALUE合計数です。ツリーラインのバイナリ性質上ので、x番目の位置にある人のうちなら、我々は範囲や位置の人の位置を取得するには、X、この位置への権利は、値0を更新し、ツリーラインを更新を見つけることができ、それこれは、人々が排除された表現できる、総数はマイナス1である、それはゲームに残っているどのように多くの人々を示すことができます。
これは、人の位置から外れていると仮定するとINX、位置の男の次のうちで彼の左(および右)A-番目、私たちは、MOD = A%(残数)、その後、我々は数の左INX(L)と右を得ることができますすることができます(R)は、その後、個人やMOD符号に基づいて次の位置を決定します。
1の#include <iostreamの> 2の#include <cmath> 3の#include <cstdioを> 4 5 の#define LL長いロング 6 7 使って 名前空間STDを、 8 9 CONST 整数 N = 5E5 + 10 。 10 構造体情報{ 11 チャー名[ 20 ]。 12 int型のターン。 13 } P [N]。 14 構造体ノード{ 15 のint L、R、値。 16 INT中間(){ リターン(L + R)>> 1 。} 17 }ツリー[N << 2 ]。 18 int型C [N]。 19 INT N、S、SS、INX。 20 INT PR [] = { 2、3、5、7、11、13、17、19、23、29 }。 21 INT マックス、NUM; 22の 23 空隙 DFS(int型 INX、INT V、int型の CNT、INT PW){ 24 以下のために(INT iが= 1 ; I <= PW; ++ I){ 25 であれば((LL)V * PR [INX]> (LL)N){ 26 であれば(最大<CNT * I){ 27 マックス= CNT * I; 28 NUM = V; 29 30 } そう であれば(CNT * I ==最大)NUM = 分(NUM、V)。 31 ブレーク; 32 } 33 他の DFS(INX + 1、V * = PR [INX]、CNT *(I + 1 )、I); 34 35 } 36 } 37 38 // 反素数模板 39 空隙AntPrime(){ 40 マックス= 1 。 41の DFS(0、1、1、30 )。 42 } 43 44 空隙 build_tree(int型 RT、INT L、INT R){ 45 ツリー[RT] .L = L。ツリー[RT] .R = R。 46 であれば(L == R){ 47 であれば(L == S)INX = RT。 48 ツリー[RT] .VALUE = 1 。 49 リターン; 50 } 51 int型のミッド= ツリー[RT] .MID()。 52 INT LSON = RT << 1 。 53 int型 rson = RT << 1 | 1 ; 54 build_tree(LSON、L、MID)。 55 build_tree(rson、ミッド+ 1 、R)。 56 ツリー[RT] .VALUE =ツリー[LSON] .VALUE + ツリー[rson] .VALUE。 57 } 58 59 空隙更新(INT X){ 60 、一方(X =!1。){ 61である - ツリー[X] .Valueの、 62は X = >> 1 ; 63れる } 64 } 65 66 空隙検索(INTの TOT、INT RT){ 67 // 位置を見つける 68 IF(ツリー[ RT] .L == ツリー[RT] .R){ 69 SS =ツリー[RT] .L; // 元の待機位置 70 INX = RT; // 更新を容易にするために、セグメントツリーの位置、 71は リターン; 72 } 73 IS int型 LSON = RT <<。1 ; 74 int型 RT = << rson 。1 | 。1 ; 75 IF(木[LSON] .Valueの> = TOT)検索(TOT、LSON); 76 他の検索(TOT - ツリー[LSON] .Valueの、rson); 77 } 78 79 ボイド)(解決{ 80 ながら(〜scanfの(" %のD%のD "、およびN-&S)){ 81 (build_tree 。1、1 、N-); 82 AntPrime(); // GETエマープと程度の数の数 83 のために(int型= I 1、I <= N; ++ I){ 84 scanfの(" %S%D "、P [I] .nameの、&P [I] .turn); 85 } 86 INT CNT = 0 ; 87 INT = REMAIN N-; 88 // S人のキュー位置うち 89 // SSは、人の元の待機位置 90 SS = S; 91である 一方で(!++ CNT = NUM){ 92 更新(INX); // セグメントツリーを更新する 93 int型回し= ABS((ダブル)P [SS] .turn)。 94 ターン%=(まま- 1 )。 95 もしターン=のまま- (ターン!)1 。 96 もし(P [SS] .turn> 0 ){ 97 INT R =まま- S。 98 であれば(R> =ターン)S = S +ターン- 1 。 99個の 他の S =ターン- R。 100 } そうでなければ{ 101 のintリットル= S - 1 。 102 場合(L> =ターン)S = L -ターン+ 1 。 103の 他の S =(残っている- 1) - (ターン- L)+ 1 。 104 } 105 // COUT << << SS << ENDL "位置です"。 106 // coutの<< << P [SS] .nameの<<てendl "人を飛び出しました"。 107 検索(s、1 )。 108 - 残ります。 109 } 110 のprintf(" %sの%D \ n " 、P [SS] .nameの、最大)。 111 } 112 } 113 114 INT のmain(){ 115 116 (解きます)。 ; 119 }