Codeforces Educational Round 18
想到再补。
CodeForces 792A New Bus Route
题意
给你一堆一维的坐标x,问你最近的两点距离以及这样最近距离的点对数。保证输入无重点。
思路
无重点就很简单了,排个序,扫一遍统计就行。
代码
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=200007;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;
LL dis[MAXN];
LL dd[MAXN];
int main()
{
_;
int n;
while(cin>>n)
{
M(dis, 0);M(dd, 0);
for(int i=0;i<n;i++)
{
cin>>dis[i];
}
sort(dis, dis+n);
LL mindis=loo, minam=0;
for(int i=1;i<n;i++)
{
LL tt=dis[i]-dis[i-1];
if(tt<mindis)
{
mindis=tt;
minam=1;
}
else if(tt==mindis) { minam++; }
}
cout<<mindis<<' '<<minam<<endl;
}
return 0;
}
CodeForces 792B Counting-out Rhyme
题意
猴子选大王。详细规则有点不同,每次数c[i]个人。
思路
直接模拟。我没模拟链表,就是加了个flag判断是否跳过这个人。
有一点注意,虽然每次的C[i]可能很大,但是最多只有100个人,每次模一下当前人数,然后一个个数也不会T。
代码
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=107;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;
int a[MAXN];
bool f[MAXN];
int co[MAXN];
int main()
{
_;
int n;
while(cin>>n)
{
int m;cin>>m;
M(a, 0);M(f, 0);M(co, 0);
for(int i=0;i<m;i++)
{
cin>>co[i];
}
int leader=1;
for(int i=0;i<m;i++)
{
co[i]=co[i]%(n-i);
for(int j=0;j<co[i];j++)
{
do
{
leader++;
if(leader>n) leader=1;
} while(f[leader]==1);
}
cout<<leader<<(i==m-1 ? '\n' : ' ');
f[leader]=1;
do
{
leader++;
if(leader>n) leader=1;
} while(f[leader]==1);
}
}
return 0;
}
CodeForces 792C Divide by Three
题意
给你一个数,位数在100000。让你删掉最少的数字,使得新的数能被3整除且没有前导0。
思路
一开始以为是dp。。就没做。。
其实被三整除,要求和被3整除。但是,被3除只可能余1或2。
所以从后往前记录一下被3除余1和2的数字的位置,各记录2个。然后在删。比如原数余1,那么可以删1个1或者2个2,比一下得到的结果(去掉前导零)谁长就行了。
为什么这么麻烦呢,因为有一种样例:2000000111。这个样例余2,但如果删2,会导致删的数太多,因为会删前导0。所以这题写起来很烦。。。各种情况。。所以被hack的多是这题。。。
代码
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=107;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;
int main()
{
_;
string s;
while(cin>>s)
{
int k=0;
while(s[k]=='0') k++;
string ss=s.substr(k, s.size()-k);
int n=ss.size();
int sum=0;
for(int i=0;i<n;i++)
{
sum+=ss[i]-'0';
}
if(sum%3==0)
{
cout<<ss<<endl;
}
else
{
int kk=sum%3;
int p11=-1, p12=-1, p21=-1, p22=-1;
for(int i=n-1;i>=0;i--)
{
if((ss[i]-'0')%3==1)
{
if(p11==-1) p11=i;
else if(p12==-1) p12=i;
}
else if((ss[i]-'0')%3==2)
{
if(p21==-1) p21=i;
else if(p22==-1) p22=i;
}
}
bool flag=0;
string ra=ss;
string rb=ss;
if(kk==1)
{
if(p11==-1&&p22==-1)
{
flag=1;
}
if(p11!=-1)
{
ra.erase(p11,1);
k=0;
while(ra[k]=='0') k++;
if(k==ra.size()&&k!=0) k--;
ra=ra.substr(k, ra.size()-k);
}
else ra="";
if(p22!=-1)
{
rb.erase(p21, 1);
rb.erase(p22, 1);
k=0;
while(rb[k]=='0') k++;
if(k==rb.size()&&k!=0) k--;
rb=rb.substr(k, rb.size()-k);
}
else rb="";
}
else if(kk==2)
{
if(p21==-1&&p12==-1)
{
flag=1;
}
if(p21!=-1)
{
ra.erase(p21, 1);
k=0;
while(ra[k]=='0') k++;
if(k==ra.size()&&k!=0) k--;
ra=ra.substr(k, ra.size()-k);
}
else ra="";
if(p12!=-1)
{
rb.erase(p11, 1);
rb.erase(p12, 1);
k=0;
while(rb[k]=='0') k++;
if(k==rb.size()&&k!=0) k--;
rb=rb.substr(k, rb.size()-k);
}
else rb="";
}
if(flag!=0||(ra.size()==0&&rb.size()==0)) cout<<-1<<endl;
else
{
cout<<(ra.size()>rb.size() ? ra : rb)<<endl;
}
}
}
return 0;
}
CodeForces 792D Paths in a Complete Binary Tree
题意
给你一颗完全二叉搜索树,就是有 2n−1 个节点那种的,编号从1开始。然后给一个起点,给一条路径(左儿子右儿子父亲),问你终点是多少。注意如果到某一步没法走,那么忽略当前字符。
思路
观察每一层,比如根节点是k,那么第一层(根节点层)可以正好整除k,下一层只能整除k/2,下一层k/4。。。
所以到某一个节点t,算一下它最大能被多少整除。假设为p。如果求父亲,那么他的父亲一定是t+p与t-p中能被2p整除却不能被4p整除的。
要是求儿子,左儿子是t-p/2,右儿子是t+p/2。
根节点没父亲,叶节点(只能被1整除)没儿子。
说起来比较绕,举个例子就好了。
代码
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=107;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;
int main()
{
_;
LL n;
while(cin>>n)
{
int root=(n+1)>>1;
int m;cin>>m;
while(m--)
{
LL k;string s;
cin>>k>>s;
LL cur=k;
for(int i=0;i<s.size();i++)
{
if(s[i]=='U')
{
if(cur==root) continue;
LL now=1;
while(cur%now==0)
{
now*=2;
}
LL a=cur+(now/2), b=cur-(now/2);
if((a/now)%2!=0) cur=a;
else cur=b;
}
else if(s[i]=='L')
{
if(cur%2==1) continue;
LL now=1;
while(cur%now==0)
{
now*=2;
}
cur=cur-(now/2/2);
}
else
{
if(cur%2==1) continue;
LL now=1;
while(cur%now==0)
{
now*=2;
}
cur=cur+(now/2/2);
}
}
cout<<cur<<endl;
}
}
return 0;
}