比赛链接:Codeforces Round #425 (Div. 2)
A:
A/B Problem
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll n,k;
cin >> n >> k;
if(n/k%2LL==0) cout << "NO" << endl;
else cout << "YES" << endl;
return 0;
}
B:
字符串处理。。。容易写错
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool ok[26];
bool solve(string &s1,string &s, string &t)
{
int l,r;
for(l=0;s[l]!='*';++l)
if((s[l]=='?'&&!ok[t[l]-'a'])||(s[l]!='?'&&s[l]!=t[l])) return false;
for(r=1;s[s.length()-r]!='*';++r)
if((s[s.length()-r]=='?'&&!ok[t[t.length()-r]-'a'])||(s[s.length()-r]!='?'&&s[s.length()-r]!=t[t.length()-r])) return false;
s1=t.substr(l,(int)t.length()-r-l+1);
return true;
}
int main()
{
string s;
cin >> s;
for(auto ch : s) ok[ch-'a']=true;
cin >> s;
bool star=false;
for(auto ch : s) if(ch=='*') star=true;
int q;
cin >> q;
while(q--)
{
string t;
cin >> t;
if(star)
{
string s1;
if(!star||t.length()<s.length()-1) cout << "NO" << endl;
else if(!solve(s1,s,t)) cout << "NO" << endl;
else
{
if(s1.length()==0) cout << "YES" << endl;
else
{
bool f=true;
for(auto ch : s1) if(ok[ch-'a']) f=false;
if(f) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
}
else
{
bool f=true;
if(s.length()!=t.length()) f=false;
else for(int i=0;i<t.length();++i)
{
if(s[i]=='?')
{
if(!ok[t[i]-'a']) f=false;
}
else if(s[i]!=t[i]) f=false;
}
if(f) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
return 0;
}
C:
题意是线段上有
n
个人,分别有各自的初始坐标,速度以及行走方向。要求你找到一个炸弹的位置,这个炸弹会在一开始爆炸并向两边射出速度为
可以二分时间
t
,设人的初始位置与人与激光相遇的位置的距离差为
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const int N=1e5+7;
int n;
const int L=1000000;
ld s;
ld v[N],d[N];
int dir[N],x[N];
struct Point
{
int x,v,d;
bool operator < (const Point &r) const
{
return x!=r.x?x<r.x:v>r.v;
}
};
vector<Point> seg;
bool check(ld t)
{
seg.clear();
int ok[2];
ok[0]=ok[1]=0;
for(int i=0;i<n;++i)
{
if(d[i]/v[i]<=t) ok[dir[i]]=1;
else if(d[i]/(v[i]+s)<=t)
{
ld d1=(t-d[i]/(v[i]+s))/(1/v[i]-1/(v[i]+s));
ld off=d[i]-d1+d1*s/v[i];
if(dir[i])
{
seg.push_back({ lround(max((ld)0,ceil(L-off))),1,dir[i] });
seg.push_back({ x[i],-1,dir[i] });
}
else
{
seg.push_back({ x[i],1,dir[i] });
seg.push_back({ lround(min((ld)L,floor(off))),-1,dir[i] });
}
}
if(ok[0]&&ok[1]) return true;
}
sort(seg.begin(),seg.end());
for(auto k : seg)
{
ok[k.d]+=k.v;
if(ok[0]&&ok[1]) return true;
}
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> s;
for(int i=0;i<n;i++)
{
cin >> x[i] >> v[i] >> dir[i] ;
--dir[i];
d[i]=dir[i]?L-x[i]:x[i];
}
ld l=0,r=L;
for(int i=0;i<50;++i)
{
ld m=(l+r)/2;
if(check(m)) r=m;
else l=m;
}
cout << fixed << setprecision(20) << r << endl;
return 0;
}
D:
求出树上终点相同的两条链的公共长度,假设要求 (a,b) 和 (b,c) 的公共长度,答案是 dis(a,b)+dis(b,c)−dis(a,c)2 。可以用LCA来做。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int d[N],anc[N][20],k,n;
vector<int> adj[N];
void dfs(int u, int father, int deep)
{
anc[u][0]=father;
d[u]=deep;
for(auto v : adj[u])
{
if(v==father) continue;
dfs(v,u,deep+1);
}
}
void init()
{
dfs(1,0,0);
for(int j=1;(1<<j)<n;j++)
{
k=j;
for(int i=1;i<=n;++i)
anc[i][j]=anc[i][j-1]?anc[anc[i][j-1]][j-1]:0;
}
}
int lca(int u,int v)
{
int res=0;
if(d[u]<d[v]) swap(u,v);
for(int i=k;i>=0;--i)
if(d[u]-(1<<i)>=d[v])
u=anc[u][i],res+=(1<<i);
if(u==v) return res;
for(int i=k;i>=0;i--)
if(anc[u][i]!=anc[v][i])
{
u=anc[u][i];
v=anc[v][i];
res+=(1<<(i+1));
}
return res+2;
}
int dis(int s,int f,int t)
{
return ((lca(s,f)+lca(t,f)-lca(s,t))>>1)+1;
}
int main()
{
ios::sync_with_stdio(false);
int q;
cin >> n >> q;
for(int u=2;u<=n;++u)
{
int v;
cin >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
init();
while(q--)
{
int a,b,c;
cin >> a >> b >> c;
int ans=0;
ans=max(ans,dis(a,b,c));
ans=max(ans,dis(a,c,b));
ans=max(ans,dis(b,a,c));
ans=max(ans,dis(b,c,a));
ans=max(ans,dis(c,a,b));
ans=max(ans,dis(c,b,a));
cout << ans << endl;
}
}