トピックリンク:https://codeforces.com/contest/1333
第二は、非常に近い過去最高に、2000以上のヒット。問題Cは、通常の再生であることを、他の表示され少しを果たしています。
- リトルアルテム
シンプルな構造、全てのn及びmのために、第1グリッドを交換し、同じ色の染色及び直接、チェッカーボードあまりにも面倒に関与する必要はありませんこのような構成に2以上必ずしも正しいです。
B - 種類アントン
簡単なシミュレーションは、ちょうどそれについて考えます。
* C - ユージーンとアレイ
+2、あまりにも悲惨な、そして最初に偽アルゴリズム+配列の範囲であり、第二は、偽のアルゴリズムです。
質問の意味:シーケンス番号nに。それは連続した部分区間0のいずれかの合計が含まれていない連続「良い」を定義します。何であるか、すべての連続需要の部分区間のこの一連の「良いです。」
解決策:この「ゼロへの合計は、」もちろん、位置キーの値のための最後の合計を保存するためのマップ<LL、int型>は、何度も見てきたようです。しかし、細部の少しがあり、以下のデータを処理します:
7
1 2 -3 4 1 2 3
選択することができる4番号4は、次のとおり[2、3,4] - 1に等しいスキップする前のステップで得られた[3,4]、[4]は、スキップされました。見つけることは非常に容易であることと(これは間隔0の合計が含まれていない可能性があるため)、その後、数が長い未満の後ろにスキップすることができ、選択可能な位置と和の同じ位置にスキップの数を制限することが一般的です。
map<ll, int> MAP;
int a[2000005];
void TestCase() {
MAP.clear();
MAP[0] = 0;
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
ll sum = 0, ans = 0;
int rightmost = 0;
for(int i = 1; i <= n; ++i) {
sum += a[i];
if(MAP.count(sum))
//printf("?\n");
rightmost = max(rightmost, MAP[sum] + 1);
ans += i - rightmost;
MAP[sum] = i;
//printf("i=%d ans=%lld\n", i, ans);
//printf(" rightmost=%d\n", rightmost);
}
printf("%lld\n", ans);
return;
}
* D - 学校の課題№41
問題の意味:矢印、唯一の左矢印キーまたは右矢印Nのシーケンスがあるが、各動作は逆の矢印に隣接する反対の矢印の組から選択することができます。少なくとも1秒あたりの動作は、Kの要求を正確になし、対向する矢印矢印全体の配列にすることができます。
:図は、以下の
1秒、反転しながら対向する矢印の二対を選択:
2秒だけ相対的に反転矢印を選択します。
問題の解決:nは偉大な小さなをKは、最初に考えたのは枯渇が矢印サイクルのステップの一部にすることが、いくつかのプッシュした後、各矢印は、明確に定義されている何回反転させることを発見します。右矢印矢印左0が1と理解するものと理解することができ、これは、バブルソートであるが、毎秒矢印のいくつかのグループが同時に互いに独立して動作させることができます。そこそれぞれの状態で見つけることができますいくつかの位置は、一時的なビット交換がされており、これらの位置は、のと同時に、互いに独立して変更することができます。可能な限りすべての状態のすべてのフリップが、それは時間の最小値である必要があります場合は、タスクを完了します。残りの操作の数が残り時間よりも小さい場合、各フリップまで可能な限り何度でも:明らかに各動作が+1(余りに激しい)だろう、貪欲アルゴリズムがあることは非常にはっきりしている2つのセクションに分けることができますステップの特定の数の後に残っている残りの動作時間に等しいです。
なお、jは、その後の再計算jの位置に、TMPを切り捨てられた場合、Jを進める際に次のコード。(幸いなことに、比較的大きな入力データ、及び数kをチェックするように構成されました)。
char s[3005];
char t[3005];
vector<pair<int, int> > ans;
void TestCase() {
int n, k;
scanf("%d%d", &n, &k);
scanf("%s", s + 1);
//puts(s + 1);
int suc = 0, Layer = 1;
while(1) {
//printf("Layer=%d\n", Layer);
suc = 1;
t[1] = s[1];
for(int i = 2; i <= n; ++i) {
if(s[i - 1] == 'R' && s[i] == 'L') {
t[i - 1] = 'L';
t[i] = 'R';
ans.push_back({Layer, i - 1});
suc = 0;
//printf("swap %d\n", i - 1);
} else
t[i] = s[i];
}
if(suc) {
--Layer;
break;
}
for(int i = 1; i <= n; ++i)
s[i] = t[i];
//puts(s + 1);
++Layer;
}
//printf("Layer=%d\n", Layer);
int m = ans.size();
//printf("sumans=%d\n", m);
if(m < k || k < Layer) {
puts("-1");
return;
}
int rest = m;
int j = 0;
while(rest > k) {
--k;
int cnt = 0;
int begin_j = j;
while(j < m && ans[j].first == ans[begin_j].first) {
++cnt;
++j;
}
int tmp = min(cnt, rest - k);
printf("%d", tmp);
j = begin_j;
for(int k = 0; k < tmp; ++k)
printf(" %d", ans[j++].second);
printf("\n");
//printf("rest k=%d\n", k);
//printf("rest ans=%d\n", m - j);
rest -= tmp;
}
assert(rest == k);
while(rest--) {
printf("1 %d", ans[j].second);
++j;
printf("\n");
}
return;
}
これは、実際にバブルソート、操作の数と逆の順序で同じ番号であるので、今理解し、どのように多くの操作が(と巧妙な直接ベクトル用)知らない始まりは、これ以上のn ^ 2のオーダーよりもあってはなりません。
なお時には、上記のようにTの反転文字列としてコピーまたはシーケンス(コピーtを覚え[1])、または操作++ iがもう一度反転後。
* F - ケイトと不完全性
質問の意味:に[1、n]は連続自然数の。kの各[2、n]は、kの全てのサイズだけ列挙サブセットを有する、その後F、Fは、すべてのタプルの集合を介してDIADを得ることパラメータの集合である関数を定義しますGCDは、その後、これらのGCDの内部の最大値を取って、最小値は各関数F kのために必要。
ソリューション:素因数の最小数をそれぞれ除去した後にソート。これは1自体を取り除くために最初の素数、優先順位付け、それらを後に残し、右の構造を見つけることは本当に簡単です。その後すぐに、行4、二度とオプションの最大公約数が1できたので、4つの作るには2が良いですGCD追加。8は4が削除挿入する必要がありますので、この時点では、8を挿入してはいけません。同様に、インサート10は、削除5がかかります。GCD 2が使い果たされているので、この場合6を挿入するには、次の図9は、8の代わりに挿入されるべきです。それはいくつかの例を記述した場合、それは、ライト12のケースだったという法律を観察することができます。
1 2 3 5 7 11 4 6 9 8 10 12
実際には、その時点で判明している、私は常にすべての首相の権限を鼓舞する必要はありませんので、すべての素数を置くだけ2を入れ、その後、唯一の2と3を入れて、この8ノー観察された法律です数が廃棄され、またそれは、各番号他の素因数に使用されず、時には最小素因数の観点から考えることができると考えています。
ゲームはまた、テンプレートメビウス反転希望の前処理を見つけた場合、\(\合計\ limits_は{私は ^ N = 1} \合計\ limits_ {J = 1} ^ nは[GCD(I、J )== K] \)の値が、それは、被験者がサブセットを選択し、選択的に、いくつかの要素間のGCDを無視しないことであるという事実を無視します。
実際には、このプロセスは次にプロセスのGCD = 1、GCD = 2、GCD = 3、GCD = 4で構成されているが、私は疑問を持っていたときGCD = 4にプッシュ。
const int MAXN = 5e5;
int p[MAXN + 5], ptop;
int pm[MAXN + 5];
void sieve() {
int n = MAXN;
pm[1] = 1;
for(int i = 2; i <= n; ++i) {
if(!pm[i]) {
p[++ptop] = i;
pm[i] = i;
}
for(int j = 1; j <= ptop; ++j) {
int t = i * p[j];
if(t > n)
break;
pm[t] = p[j];
if(i % p[j])
;
else
break;
}
}
}
void TestCase() {
sieve();
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
pm[i] = i / pm[i];
sort(pm + 1, pm + 1 + n);
for(int i = 2; i <= n; ++i)
printf("%d%c", pm[i], " \n"[i == n]);
return;
}