Codeforces Round #627 (Div. 3)
Codeforces Round #627 (Div. 3)
难道这会是我第一场能补完题的cf场?虽然是div3
A. Yet Another Tetris Problem
题意
给一个俄罗斯方块的残局,每次可以放一个高2宽1的块,问能否全部消除
题解
检测一下所有数的奇偶性,全部相同就可以消除
ps:题意懂了就是手速题
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{ long _,n,i,x,a1,a0;
for(scanf("%ld",&_);_;_--){
scanf("%ld",&n);
a0=a1=0;
for(i=1;i<=n;i++){
scanf("%ld",&x);
if(x%2)a1++;
else a0++;
}
if(a1==n||a0==n)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
B. Yet Another Palindrome Problem
题意
给一串数字,求能否构成长度不小于3的回文串,取的数可以不连续但是相对顺序不可变
题解
因为可以不连续,只要找有两位相等的而且不相邻就好了
ps:又是手速题
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define def 5010
using namespace std;
long a[def];
int main()
{ long _,n,i,j;
for(scanf("%ld",&_);_;_--){
scanf("%ld",&n);
for(i=1;i<=n;i++)
scanf("%ld",&a[i]);
bool t=false;
for(i=1;i<=n;i++)
for(j=i+2;j<=n;j++)
if(a[i]==a[j]){
t=true;
break;
}
if(t)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
C. Frog Jumps
题意
青蛙过河,河中每个石子有自己的属性L和R,L只能向左跳,R只能向右跳,每次最多跳\(k\)步,求能过河的最小的\(k\)
题解
只要保证每次都能跳到R就能过河,所以最小值就是\(max\){起点到第一个R的距离,最后一个R到终点的距离,max{两个R之间的距离}}
ps:刚开始有了思维定势,直接去想二分了,还好后来改了回来
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define max(a,b) (((a)>(b))?(a):(b))
using namespace std;
int main()
{ long _,ans,i;
string s;
for(scanf("%ld",&_);_;_--){
cin>>s;
s='R'+s+'R';
ans=0;
for(i=0;i<s.length()-1;i++)
if(s[i]=='R')
ans=max(ans,s.find("R",i+1)-i);
printf("%ld\n",ans);
}
return 0;
}
D. Pair of Topics
题意
给出两个数列,找出满足\(a_i+a_j>b_i+b_j (i<j)\)的对数
题解
移项,\(a_i-b_i>b_j-a_j(i<j)\),这样就变成了\(c_i>-c_j(i<j)\)
这样问题变成了:计算某个数之前有几个数比他的相反数小,典型的离散化+树状数组
ps:开局直接开了D,还好不难,心态没崩,不过好像我的方法不是最简单的?
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#define ll long long
#define lowbit(i) ((i)&0-(i))
#define def 400010
using namespace std;
map<ll,long>mp;
long sum[def];
ll a[def],b[def];
//树状数组
void add(long x,long y)
{
for(;x<def;x+=lowbit(x))
sum[x]+=y;
}
long query(long x)
{ long ans=0;
for(;x;x-=lowbit(x))
ans+=sum[x];
return ans;
}
int main()
{ long n,i,cnt=0;
ll ans=0,x;
scanf("%ld",&n);
for(i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(i=1;i<=n;i++){
scanf("%lld",&x);
a[i]-=x;
}
//离散化
for(i=1;i<=n;i++){
b[i]=a[i];
b[i+n]=-a[i];
}
sort(b+1,b+2*n+1);
b[2*n+1]=b[2*n]+1;
for(i=1;i<=2*n;i++)
if(b[i]!=b[i+1])
mp[b[i]]=++cnt;
//统计
for(i=1;i<=n;i++){
ans+=i-1-query(mp[-a[i]]);
add(mp[a[i]],1);
}
printf("%lld\n",ans);
return 0;
}
E. Sleeping Schedule
题意
一个人睡觉一次睡一天,第\(i\)次醒来后\(a_i\)或者\((a_i-1)\)小时后才会再次睡觉,每天有\(h\)小时,其中在\([l,r]\)小时区间内睡着就是一个“好睡眠”,从第1天的0时开始醒来,求最多能得到的“好睡眠”数
题解
n是2000,h是2000,很容易想对他们动心思,然后就想到了二维dp,用\(f_{i,j}\)表示第i-1次在第j小时醒来,到最后能得到的最多“好睡眠”数,方程挺好写的,具体实现见代码
ps:比赛时wa40我也是第一次见,后来发现忘了特判第一天QAQ
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define def 2010
using namespace std;
long long a[def],f[def][def];
int main()
{ long long n,h,l,r,i,j;
scanf("%lld%lld%lld%lld",&n,&h,&l,&r);
for(i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(i=l;i<=r;i++)
f[n+1][i]=1;
for(i=n;i>=1;i--)
for(j=0;j<h;j++){
f[i][j]=max(f[i+1][(j+a[i])%h],f[i+1][(j+a[i]-1+h)%h]);
if(l<=j&&j<=r&&i!=1)
f[i][j]++;
}
printf("%lld\n",f[1][0]);
return 0;
}
F. Maximum White Subtree
10:30 我去补题,这次一定不咕
11:36 没咕没咕
题意
给出一颗无根树,每个点有一个颜色(黑/白),求每个点的包含他的子树中,黑白点数差值最大多少
题解
首先指定一个根,比如1为根,然后求出每个点为根的子树里黑白点数最大差值
接着进行一次dp,算出每个点作为根节点时的黑白最大差值
现在的重点是dp时的转移,上边已经求出了\(f_i\)表示以i为根的子树的黑白最大差,那么以i为根节点的黑白最大差\(ans_i=max(ans_{fa}-max(f_i,0),0)+f_i\)
ps:英文不好,理解错题,耽搁了QAQ
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define def 200010
using namespace std;
vector<long>mp[def];
long fa[def],f[def],ans[def],a[def];
long max(long a,long b)
{
return a>b?a:b;
}
long dfs(long now)
{ long sum=0;
for(auto next:mp[now])
if(next!=fa[now]){
fa[next]=now;
f[next]=dfs(next);
sum+=max(f[next],0);
}
return sum+a[now];
}
void dp(long now)
{
ans[now]=max(ans[fa[now]]-max(f[now],0),0)+f[now];
for(auto next:mp[now])
if(next!=fa[now])
dp(next);
}
int main()
{ long n,i,x,y,minn,sum;
scanf("%ld",&n);
for(i=1;i<=n;i++){
scanf("%ld",&a[i]);
a[i]=a[i]?1:-1;
}
for(i=1;i<n;i++){
scanf("%ld%ld",&x,&y);
mp[x].push_back(y);
mp[y].push_back(x);
}
fa[1]=0;
f[1]=dfs(1);
dp(1);
for(i=1;i<=n;i++)
printf("%ld ",ans[i]);
printf("\n");
return 0;
}
_______________________________________________
终于有一次赛后ak的了,红红火火恍恍惚惚