Educational Codeforces Round 18
A. New Bus Route
排个序找最小的差值
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
void solve(){
int n;
cin >> n;
vector<int> vec(n);
for(int &x : vec) cin >> x;
sort(vec.begin(),vec.end());
map<int,int> msk;
for(int i = 1; i < n; i++) msk[vec[i]-vec[i-1]]++;
cout << msk.begin()->first << ' ' << msk.begin()->second << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}
B.Counting-out Rhyme
按题意模拟即可
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
void solve(){
____();
int n, k;
static bool vis[200];
cin >> n >> k;
int cur = 0;
memset(vis,0,sizeof(vis));
for(int t = 0; t < k; t++){
int x; cin >> x;
x %= (n-t);
for(int i = 0; i < x; i++){
while(vis[(cur+1)%n]) cur = (cur + 1) % n;
cur = (cur + 1) % n;
}
vis[cur] = true;
cout << cur + 1 << ' ';
while(vis[(cur+1)%n]) cur = (cur + 1) % n;
cur = (cur + 1) % n;
}
cout << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}
C. Divide by Three
先去掉前导零,然后分模\(3\)余数分类讨论
余\(0\)直接输出
余\(1\)找一个模\(3\)余\(1\)的或者两个模\(3\)余\(2\)的
余\(2\)找一个模\(3\)余\(2\)的或者两个模\(3\)余\(1\)的
保留最长的即可
注意判断\(0\)的情况
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
char s[MAXN];
int n;
void solve(){
cin >> s + 1;
n = strlen(s+1);
reverse(s+1,s+1+n);
bool havez = false;
for(int i = 1; i <= n; i++) if(s[i]=='0') havez = true;
int tot = 0;
for(int i = 1; i <= n; i++) tot += s[i] - '0';
while(n and s[n]=='0') n--;
if(!n){
cout << 0 << endl;
return;
}
if(tot%3==0){
reverse(s+1,s+1+n);
cout << s + 1 << endl;
return;
}else if(tot%3==2){
string ss(s+1,s+1+n);
string s1(""), s2 = s1;
int pos = -1;
for(int i = 0; i < n; i++) if((ss[i] - '0') % 3==2){
pos = i;
break;
}
if(pos!=-1){
ss[pos] = 'a';
string sb("");
for(int i = 0; i < n; i++) if(isdigit(ss[i])) sb+=ss[i];
while(!sb.empty() and sb.back()=='0') sb.pop_back();
s1 = sb;
}
ss = string(s+1,s+1+n);
int p1 = -1, p2 = -1;
for(int i = 0; i < n; i++) if((ss[i] - '0') % 3 == 1){
if(p1==-1) p1 = i;
else p2 = i;
if(p2!=-1) break;
}
if(p2!=-1){
ss[p1] = ss[p2] = 'a';
string sb("");
for(int i = 0; i < n; i++) if(isdigit(ss[i])) sb+=ss[i];
while(!sb.empty() and sb.back()=='0') sb.pop_back();
s2 = sb;
}
if(s1.empty() and s2.empty()){
if(havez) cout << "0" << endl;
else cout << -1 << endl;
}else{
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
if(s1.length() > s2.length()) cout << s1 << endl;
else cout << s2 << endl;
}
}else{
string ss(s+1,s+1+n);
string s1(""), s2 = s1;
int pos = -1;
for(int i = 0; i < n; i++) if((ss[i] - '0') % 3==1){
pos = i;
break;
}
if(pos!=-1){
ss[pos] = 'q';
string sb("");
for(int i = 0; i < n; i++) if(isdigit(ss[i])) sb+=ss[i];
while(!sb.empty() and sb.back()=='0') sb.pop_back();
s1 = sb;
}
ss = string(s+1,s+1+n);
int p1 = -1, p2 = -1;
for(int i = 0; i < n; i++) if((ss[i] - '0') % 3 == 2){
if(p1==-1) p1 = i;
else p2 = i;
if(p2!=-1) break;
}
if(p2!=-1){
ss[p1] = ss[p2] = 'a';
string sb("");
for(int i = 0; i < n; i++) if(isdigit(ss[i])) sb+=ss[i];
while(!sb.empty() and sb.back()=='0') sb.pop_back();
s2 = sb;
}
if(s1.empty() and s2.empty()){
if(havez) cout << "0" << endl;
else cout << -1 << endl;
}else{
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
if(s1.length() > s2.length()) cout << s1 << endl;
else cout << s2 << endl;
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}
D. Paths in a Complete Binary Tree
观察后可以发现每一层的编号的\(lowbit\)都是相同的,往上一层,\(lowbit\)大\(1\),往下一层\(lowbit\)小\(1\)
然后直接一步步转移即可
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
#define lowbit(x) ((x) & -(x))
void solve(){
____();
LL n; cin >> n;
int q; cin >> q;
while(q--){
LL u; string s;
cin >> u >> s;
for(auto &ch : s){
if(ch=='U'){
if(u==(n+1)/2) continue;
if(lowbit(u+lowbit(u))==lowbit(u)*2) u += lowbit(u);
else u -= lowbit(u);
}else if(ch=='L'){
if(lowbit(u)==1) continue;
u -= (lowbit(u) / 2);
}else if(ch=='R'){
if(lowbit(u)==1) continue;
u += (lowbit(u) / 2);
}
}
printf("%I64d\n",u);
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}
E.Colored Balls
可以发现块的大小和块的数量不会同时超过\(\sqrt {A_{min}}\)
那么我们枚举块的大小来做就好了
注意一些特殊情况
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
const int MAXN = 555;
const int N = 4e4+7;
void solve(){
static int n, A[MAXN];
cin >> n;
for(int i = 1; i <= n; i++) cin >> A[i];
LL ret = INT_FAST64_MAX;
auto check = [&](int k){
LL cnt = 0;
bool ok = true;
for(int i = 1; i <= n; i++){ // k and k + 1
if(A[i]%(k+1)==0){
cnt += A[i] / (k+1);
continue;
}
if(k - A[i] % (k+1) <= A[i] / (k+1)){
cnt += A[i] / (k + 1) + 1;
continue;
}
cnt += A[i] / k;
if(A[i]%k > A[i]/k){
ok = false;
break;
}
}
return ok ? cnt : INT64_MAX;
};
for(int k = 1; k <= N; k++){
ret = min(ret,check(k));
if(A[1]/k) ret = min(ret,check(A[1]/k));
if(A[1]/k-1>0) ret = min(ret,check(A[1]/k-1));
}
cout << ret << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}
F. Mages and Monsters
考虑维护出每秒造成\(x\)点伤害的最小魔法消耗
我们把每次学习的技能看作二维笛卡尔坐标系上的点,横坐标是每秒伤害,纵坐标是每秒消耗
我们希望造成相同伤害的情况下用尽量少的\(MP\),那么我们可以动态维护一个下凸包
对于每次查询,我们找到对应的平均伤害即\(h/t\)对应的位置,如果找不到或者需要的消耗大于了总的\(MP\)就输出\(NO\)否则输出\(YES\)
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef pair<double,double> pdd;
typedef long long int LL;
const int M = 1000000;
const double eps = 1e-9;
int n;
double m;
set<pdd> S;
double operator *(pdd A, pdd B){ return A.first * B.second - A.second * B.first; }
pdd operator -(pdd a, pdd b){ return {a.first - b.first,a.second - b.second}; }
double X(pdd a, pdd b, pdd c){ return (b-a) * (c-a); }
void try_insert(double damage, double cost){
pdd p = {damage,cost};
auto it = S.lower_bound({p.first,0});
if(it!=S.end() and it->second<=p.second) return;
auto pre = it; --pre;
if(it!=S.end() and X(*pre,p,*it)<=eps) return;
it = S.insert(p).first;
pre = it; pre--;
while(pre!=S.begin()){
auto ppre = pre; ppre--;
if(X(*ppre,*pre,*it)<=eps) S.erase(pre--);
else break;
}
auto nxt = it; nxt++;
while(nxt!=--S.end() and nxt!=S.end()){
auto nnxt = nxt; nnxt++;
if(X(*it,*nxt,*nnxt)<=eps) S.erase(nxt++);
else break;
}
}
bool test(double t, double h){
auto it = S.lower_bound({h/t,0});
if(it==S.end()) return false;
auto pre = it; pre--;
double cost = (it->second - pre->second) / (it->first - pre->first) * (h/t - pre->first) + pre->second;
return m - cost * t >= -eps;
}
void solve(){
____();
cin >> n >> m;
S.insert({0,0});
int lastans = 0;
for(int i = 1; i <= n; i++){
int k, a, b;
cin >> k >> a >> b;
a = (a + lastans) % M + 1;
b = (b + lastans) % M + 1;
if(k==1) try_insert(a,b);
else{
if(test(a,b)) puts("YES"), lastans = i;
else puts("NO");
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}