# Разбор задач 2016 года Если Вы не знали как решать какую-то задачу и Вам было лень разбираться в коде на Pascal, то это пост специально для Вас. :::warning Убедительная просьба не копировать коды и не пересылать их. Помните -- Вы решаете задачи для себя! ::: ## [1. Движение по кольцу](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2016_1) :::spoiler Разбор :::info Паша может жить либо на $m$ остановок левее школы, либо на $m$ остановок правее школы. Считаем местоположение дома Паши. Не забудем, что его можно определить однозначно. Асимптотика: $O(1)$. ::: :::spoiler Авторское решение (Pascal) ```pascal var n,m,k,x1,x2:longint; begin read(n,k,m); x1:=(k + m) mod n + 1; x2:=(n + k - m - 2) mod n + 1; if 2*m+2>=n then if x1=x2 then writeln(x1) else if x1<x2 then writeln(x1, ' ', x2) else writeln(x2, ' ', x1) end. ``` ::: :::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko)) ```cpp #include <bits/stdc++.h> using namespace std; int main() { long long n, m, k; cin >> n >> k >> m; m++; set<long long> ans; long long ost_1 = k - m; if (ost_1 >= 1) ans.insert(ost_1); else ans.insert(ost_1 + n); long long ost_2 = k + m; if (ost_2 <= n) ans.insert(ost_2); else ans.insert(ost_2 - n); for (auto to : ans) cout << to << " "; cout << endl; return 0; } ``` ::: ## [2. Крутейший спуск](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2016_2) :::spoiler Разбор :::info В этой задаче нам нужно найти максимальное отношение перепада высот к расстоянию между отметками по горизонтали. Мы делаем ровно то, о чем нас просят. Единственный момент: чтобы избежать неточностей, давайте заменим отношение умножением крест-накрест ($\frac{A}{B} = \frac{C}{D}$ равносильно $A * D = B * C$). Асимптотика: $O(N)$. ::: :::spoiler Авторское решение (Pascal) ```pascal function abs(x:longint):longint; begin if x<0 then abs:=-x else abs:=x end; var n,xp,hp,xc,hc,i,mp,dx,dh,mdx,mdh:longint; begin read(n); read(xp,hp,xc,hc); mp:=1; mdx:=abs(xp-xc); mdh:=abs(hp-hc); for i:=2 to n-1 do begin xp:=xc;hp:=hc; read(xc,hc); dx:=abs(xp-xc); dh:=abs(hp-hc); if int64(dh)*mdx>int64(mdh)*dx then begin mp:=i; mdx:=dx; mdh:=dh end end; writeln(mp) end. ``` ::: :::spoiler Код (C++, автор: [gamora](https://codeforces.com/profile/gamora)) ```cpp #include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; int lasth, lastd; cin >> lastd >> lasth; int d, h; cin >> d >> h; int H = abs(lasth - h); int D = abs(lastd - d); int otH = H, otD = D, nom = 1, j = 1; for (int i = 2; i < n; i++) { j++; lastd = d; lasth = h; cin >> d >> h; H = abs(lasth - h); D = abs(lastd - d); if (otH * D < H * otD) { otH = H; otD = D; nom = j; } } cout << nom << endl; return 0; } ``` ::: ## [3. Самый длинный слог](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2016_3) :::spoiler Разбор :::info Это очень запарная и неприятная реализация. Разбираем все случаи (они описаны в условии). Выводим ответ. Асимптотика: $O(N + |allS|)$, где $|allS|$ -- длина всех строк. ::: :::spoiler Авторское решение (Pascal) ```pascal var i,st,p,m,mp,k:longint; s:ansistring; begin readln(s); st:=1; p:=0; m:=0; mp:=0; for i:=1 to length(s) do case s[i] of ' ': begin if m < i-st then begin m:=i-st; mp:=st end; st:=i+1; p:=0 end; 'a','e','i','o','u','y' : begin if p<>0 then begin if (s[p] = 'y') or (i<=p+2) then k := p else k:=p+1; if m < k + 1 - st then begin m := k + 1 - st; mp:=st end; st := k + 1 end; p:=i end end; k:=length(s); if m < k + 1 - st then begin m := k + 1 - st; mp:=st end; writeln(copy(s,mp,m)) end. ``` ::: :::spoiler Код (C++, автор: [Zhdun](https://codeforces.com/profile/Zhdun)) ```cpp #include <bits/stdc++.h> using namespace std; vector<string> w; int main() { string s; getline(cin,s); string cur = ""; for (int i = 0; i < s.size(); i++) if (s[i] == ' ') { w.push_back(cur); cur = ""; } else cur += s[i]; if (cur != "") w.push_back(cur); int ma=0; string ans; for (int i = 0; i < w.size(); i++) { vector<int> gl; int pr = -1; for (int j = 0; j < w[i].size(); j++) if (w[i][j]=='a' || w[i][j]=='e' || w[i][j]=='y' || w[i][j]=='i' || w[i][j]=='o' || w[i][j]=='u') gl.pb(j); int cur = 0; string t; for (int j = 0; j < w[i].size(); j++) if (cur == 0 && j < gl[0]) t += w[i][j]; else if(cur == gl.size()-1 && j >= gl[cur]) t+=w[i][j]; else if (gl[cur] == j && cur != gl.size()-1) { t += w[i][j]; cur++; if (gl[cur] - gl[cur-1] <= 2 || w[i][j] == 'y') { if (t.size() > ma) { ans = t; ma = t.size(); } t = ""; } } else if (gl[cur-1] == j-1) { t += w[i][j]; if (t.size()>1) { if (t.size() > ma) { ans = t; ma = t.size(); } t = ""; } } else t+=w[i][j]; if(t != "") { if (t.size() > ma) { ans = t; ma = t.size(); } t = ""; } } cout << ans << endl; } ``` ::: ## [4. Пессимистичный прогноз](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2016_4) :::spoiler Разбор :::info Давайте напишем жадный алгоритм. Вначале отсортируем все команды по рейтингу (он описан в условии). Теперь все команды, которые выше $k$-й, мы трогать не будем (выдавать медали). Оставшимся командам будем жадно выдавать медали по следующему алгоритму: 1. Пытаемся выдать на $1$ бронзовую медаль больше, чем у $k$-й (если можем), при этом уравниваем количество золотых и серебрянных медалей. 2. Пытаемся выдать на $1$ серебрянную медаль больше, чем у $k$-й (если можем), при этом уравниваем количество золотых медалей. 3. Пытаемся выдать на $1$ золотую медаль больше чем у $k$-й (если можем). Асимптотика решения: $O(N * log(N))$. ::: :::spoiler Авторское решение (Pascal) ```pascal var n,k,i,ig,wani4ka,ib,x,mx:integer; rg,rs,rb:integer; g,s,b:array[1..300]of byte; f:array[0..300,0..60,0..60,0..60] of integer; {p:array[1..300,0..60,0..60,0..60] of (gold,silver,bronze,none);} function greater:boolean; begin if g[i]=g[k] then if s[i]=s[k] then greater:=b[i]>b[k] else greater:=s[i]>s[k] else greater:=g[i]>g[k] end; function byGold:integer; var dg:integer; begin dg:=g[k]-g[i]+1; if dg<=ig then byGold:=f[i-1,ig-dg,wani4ka,ib]+1 else byGold:=0 end; function bySilver:integer; var dg,ds:integer; begin dg:=g[k]-g[i]; ds:=s[k]-s[i]+1; if ds < 0 then ds := 0; if (dg<=ig) and (ds<=wani4ka) then bySilver:=f[i-1,ig-dg,wani4ka-ds,ib]+1 else bySilver:=0 end; function byBronze:integer; var dg,ds,db:integer; begin dg:=g[k]-g[i]; ds:=s[k]-s[i]; if ds >= 0 then begin db:=b[k]-b[i]+1; if db < 0 then db := 0; if (dg<=ig) and (ds<=wani4ka) and (db<=ib) then byBronze:=f[i-1,ig-dg,wani4ka-ds,ib-ib]+1 else byBronze:=0; end else byBronze:=0; end; begin read(n,k,rg,rs,rb); for i:=1 to n do read(g[i],s[i],b[i]); for ig:=0 to rg do for wani4ka:=0 to rs do for ib:=0 to rb do f[0,ig,wani4ka,ib]:=0; for i:=1 to n do if i=k then for ig:=0 to rg do for wani4ka:=0 to rs do for ib:=0 to rb do begin f[i,ig,wani4ka,ib]:=f[i-1,ig,wani4ka,ib]; // p[i,ig,wani4ka,ib]:=none; end else if greater then for ig:=0 to rg do for wani4ka:=0 to rs do for ib:=0 to rb do begin f[i,ig,wani4ka,ib]:=f[i-1,ig,wani4ka,ib]+1; // p[i,ig,wani4ka,ib]:=none; end else for ig:=0 to rg do for wani4ka:=0 to rs do for ib:=0 to rb do begin f[i,ig,wani4ka,ib]:=f[i-1,ig,wani4ka,ib]; // p[i,ig,wani4ka,ib]:=none; x:=byGold; if x>f[i,ig,wani4ka,ib] then begin f[i,ig,wani4ka,ib]:=x; // p[i,ig,wani4ka,ib]:=gold end; x:=bySilver; if x>f[i,ig,wani4ka,ib] then begin f[i,ig,wani4ka,ib]:=x; // p[i,ig,wani4ka,ib]:=silver end; x:=byBronze; if x>f[i,ig,wani4ka,ib] then begin f[i,ig,wani4ka,ib]:=x; // p[i,ig,wani4ka,ib]:=bronze end end; mx:=0; for ig:=0 to rg do for wani4ka:=0 to rs do for ib:=0 to rb do if f[n,ig,wani4ka,ib]>mx then begin mx:=f[n,ig,wani4ka,ib]; { mig:=ig; mis:=wani4ka; mib:=ib} end; writeln(mx); { i:=n; while i>0 do begin case p[i,mig,mis,mib] of gold : begin writeln(i); mig:=mig-(g[k]-g[i]+1) end; silver : begin writeln(i); mig:=mig-(g[k]-g[i]); mis:=mis-(s[k]-s[i]+1) end; bronze : begin writeln(i); mig:=mig-(g[k]-g[i]); mis:=mis-(s[k]-s[i]); mib:=mib-(b[k]-b[i]+1) end; end; i:=i-1 end} end. ``` ::: :::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko)) ```cpp #include <bits/stdc++.h> using namespace std; struct node { int Gold, Silver, Bronze; int id; node() { Gold = 0; Silver = 0; Bronze = 0; id = -1; } bool operator < (const node &x) { if (x.Gold != Gold) return x.Gold > Gold; else if (x.Silver != Silver) return x.Silver > Silver; else return x.Bronze > Bronze; } }; vector<node> all; int kol_Gold = 0; int kol_Silver = 0; int kol_Bronze = 0; int main() { int n, k; cin >> n >> k >> kol_Gold >> kol_Silver >> kol_Bronze; all.resize(n); for (int i = 0; i < n; ++i) { cin >> all[i].Gold >> all[i].Silver >> all[i].Bronze; all[i].id = i + 1; } sort(all.rbegin(), all.rend()); int ans = 0; bool ok = 1; node Team; for (int i = 0; i < n; ++i) { if (all[i].id != k && ok) { ans++; continue; } if (all[i].id == k) { ok = 0; Team = all[i]; continue; } int need_Gold = -all[i].Gold + Team.Gold; int need_Silver = -all[i].Silver + Team.Silver; int need_Bronze = -all[i].Bronze + Team.Bronze; if (need_Gold <= kol_Gold && need_Silver <= kol_Silver && need_Bronze + 1 <= kol_Bronze) { kol_Gold -= (need_Gold < 0 ? 0 : need_Gold); kol_Silver -= (need_Silver < 0 ? 0 : need_Silver); kol_Bronze -= (need_Bronze >= 0 ? need_Bronze + 1 : 0); ans++; continue; } if (need_Gold <= kol_Gold && need_Silver + 1 < kol_Silver) { kol_Gold -= (need_Gold < 0 ? 0 : need_Gold); kol_Silver -= (need_Silver >= 0 ? need_Silver + 1 : 0); ans++; continue; } if (need_Gold + 1 <= kol_Gold) { kol_Gold -= (need_Gold >= 0 ? need_Gold + 1 : 0); ans++; continue; } } cout << ans << endl; return 0; } ``` :::