B. Little Girl and Game
Codeforces Round 169 (Div. 2)
#博弈游戏
两人轮流删去字符串中的一个字符,如果删去之后,可以重排获得回文字符串,则对方赢。两人都选择最优策略,谁会赢?
重排则不考虑字符顺序,处理所有字符计数。什么样的字符串可以构成回文串?字母计数全是偶数,或者有一个奇数。
如果初始条件如上,那么a赢。
如果有多个奇数呢?ab都会尽量避免白送,不会让对方赢。
比如2 3 3 ->A1 3 3 ->B 0 3 3 ->A 0 2 ->B赢
比如1 1 1 ->A 0 1 1 ->B 0 0 1->A赢
比如 1 1 2->A 1 1 1->…->B赢
偶数没有作用,所有的计数都可以归为0或1。如果有两个以上的奇数,并且计数之和是偶数,那么B赢;如果有两个以上的奇数,并且计数之和是奇数,那么A赢
int cnt[26];
signed main(){
IOS;
string s;cin>>s;
fer(i,0,s.size()){
cnt[s[i]-'a']++;
}
fer(i,0,26){
if(cnt[i]%2==1){
if(s.size()%2==1)cout<<"First"<<endl;
else cout<<"Second"<<endl;
return 0;
}
}
cout<<"First"<<endl;
return 0;
}
A. Points on Line
Codeforces Round 153 (Div. 1)
#二分
IOS;
int n,d;cin>>n>>d;
fer(i,0,n)cin>>a[i];
int cnt=0;
int l,r;
fer(i,0,n-2){
l=i+2;r=n-1;
while(l<r){
int mid=(l+r+1)>>1;
if(a[mid]-a[i]>d)r=mid-1;
else l=mid;
}
if(a[l]-a[i]<=d){
int tmp=l-i-1;//右端点
cnt+=(1+tmp)*tmp/2;
}
}
cout<<cnt<<endl;
return 0;
}
A. Mocha and Math
Codeforces Round 738 (Div. 2)
#位运算
经过一番操作使得序列的最大值最小
按位与只会让数字越来越小,因此把序列的所有数与一遍就是答案
const int N=105,mod=1e9+7;
int a[N];
signed main(){
IOS;
cf{
int n;cin>>n;
fer(i,0,n)cin>>a[i];
int res=a[0];
fer(i,1,n)res=res&a[i];
cout<<res<<endl;
}
return 0;
}
A. Party
Codeforces Beta Round 87 (Div. 1 Only)
有点像并查集。求多棵树的最大深度
构造树还需要额外的数据结构,这个题n只有2e3,n^2完全可以ac,因此直接简单粗暴遍历一遍
const int N=2e3+1,mod=1e9+7;
int a[N];
signed main(){
IOS;
int n;cin>>n;
fer(i,1,n+1)cin>>a[i];
int mx=0;
fer(i,1,n+1){
int cnt=0;
int now=i;
while(a[now]!=-1){
cnt++;
now=a[now];
}
mx=max(mx,cnt+1);
}
cout<<mx;
return 0;
}
A. Hossam and Combinatorics
#排序
Codeforces Round 837 (Div. 2)
找出多少对差为最大值的i,j
普通情况是cntl*cntr*2
特殊情况是所有数字一样,cnt*(cnt-1)
const int N=1e5+5,mod=1e9+7;
int a[N];
signed main(){
IOS;
cf{
int n;cin>>n;
fer(i,0,n)cin>>a[i];
sort(a,a+n);
int mx=a[n-1]-a[0];
int cntl=0,cntr=0;
fer(i,0,n){
if(a[i]==a[0])cntl++;
else break;
}
for(int i=n-1;i>=cntl;i--){
if(a[i]==a[n-1])cntr++;
else break;
}
if(cntr==0)cout<<cntl*(cntl-1)<<endl;
else cout<<cntl*cntr*2<<endl;
}
return 0;
}
A. Deadline
#数学
Educational Codeforces Round 80 (Rated for Div. 2)
求
x
+
d
x
+
1
x+\frac{d}{x+1}
x+x+1d的最小值,类似对勾函数
signed main(){
IOS;
cf{
int n,d;cin>>n>>d;
int tmp=sqrt(d);
int mn=1e18;
fer(i,max((long long)0,tmp-10000),min(d+1,tmp+10000)){
int res;
res=i+d/(i+1);
if(i&&d%(i+1)!=0)res++;
if(res<=mn)mn=res;
else break;
}
if(mn<=n)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
B. Spoilt Permutation
#模拟
Codeforces Beta Round 52 (Div. 2)
const int N=1e3+1,mod=1e9+7;
int a[N];
signed main(){
IOS;
int n;cin>>n;
fer(i,0,n)cin>>a[i];
int i=0;
for(i;i<n;i++){
if(a[i]!=i+1)break;
}
int l=i+1,r=a[i];
bool f=1;
fer(j,i+1,r-1){
if(a[j]==a[j-1]-1)continue;
else{
f=0;break;
}
}
if(f){
fer(j,r,n){
if(a[j]!=j+1){
f=0;break;
}
}
}
if(f&&l!=n+1)cout<<l<<" "<<r<<endl;
else cout<<"0 0"<<endl;
return 0;
}
B - Coloring a Tree
Codeforces Round 453 (Div. 2)
类似并查集。模拟是从根向叶子染,如果和父节点颜色相同,则不需要多染色一次,如果不同,则需要染色。实际上不需要模拟,只需要计数。
int fa[N],c[N];
signed main(){
IOS;
int n;cin>>n;
fa[1]=-1;
fer(i,2,n+1)cin>>fa[i];
int cnt=0;
fer(i,1,n+1){
cin>>c[i];
if(c[i]!=c[fa[i]])cnt++;
}
cout<<cnt;
return 0;
}
C. Zero-Sum Prefixes
Codeforces Round 833 (Div. 2)
修改序列中0为任意整数,使得前缀和=0的个数最多
从后往前去处理,如果遇到ai==0,那么处理;如果没遇到,那么把前缀和放进map,以备后用:挑出前缀和个数最多的那个值,用0去抵消
为什么是倒着处理?因为前面抵消了,后面才能出现prefix=0
为什么不管=0的sum?因为要改ai的话sum=0也没用,还是会变。不要考虑现在有几个0,而要考虑怎么能获得最多的0
const int N=2e5+5,mod=1e9+7;
int a[N],sum[N];
signed main(){
IOS;
cf{
int n;cin>>n;
fer(i,1,n+1){
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
int cnt=0;
map<int,int>mp;
for(int i=n;i>=1;i--){
mp[sum[i]]++;
if(!a[i]){
int mx=0;
for(auto k:mp)mx=max(mx,k.second);
cnt+=mx;
mp.clear();
}
}
cnt+=mp[0];
cout<<cnt<<endl;
}
return 0;
}
F. Vitaly and Advanced Useless Algorithms
#动态规划
Codeforces Round 776 (Div. 3)
对每个任务,挑出最快使得进度到达100的方式