文章目录
题目
A Yet Another Tetris Problem
问题:俄罗斯方块,只能用宽为1,高为2的木块,给初始高度,问是否可以全部消掉。
答案:当初始高度奇偶性全部相同的时候可以全部消掉。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[101];
int main(){
ll t;
cin>>t;
while(t--){
ll n;
cin>>n;
bool flag=true;
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(ll i=2;i<=n;i++){
if((a[i]&1)!=(a[i-1]&1)){
flag=false;
break;
}
}
if(flag)puts("YES");
else puts("NO");
}
}
B Yet Another Palindrome Problem
问题:给一个序列,判断是否有长度大于等于3的子序列是回文串。
答案:判断是否有两个相等的数不相邻即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ll t;
cin>>t;
while(t--){
ll n;
cin>>n;
map<ll,ll>mp;
bool flag=false;
for(ll i=1;i<=n;i++){
ll x;
cin>>x;
if(mp[x]&&i-mp[x]>1)
flag=true;
if(!mp[x]){
mp[x]=i;
}
}
if(flag)
puts("YES");
else
puts("NO");
}
}
C Frog Jumps
问题:青蛙从0跳到n+1,在0时只能向左跳,给一个长为n的字符串,若第i位’R’则在i位置只能向右跳,若第i位为’L’则在i位置只能向左跳,每次条约距离不大于d,问最小的d是多少。
答案:最小的d为0到第一个’R’的距离,相邻’R’的距离,最后一个’R’到n+1的距离中的最小值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ll t;
cin>>t;
while(t--){
string s;
cin>>s;
ll cur=0;
ll MAX=0;
for(ll i=0;i<s.size();i++){
if(s[i]=='R'){
MAX=max(MAX,i+1-cur);
cur=i+1;
}
}
MAX=max(MAX,s.size()+1-cur);
cout<<MAX<<endl;
}
}
D Pair of Topics
问题:给两个长度为n的序列a和b,问序列中满足
a
i
+
a
j
>
b
i
+
b
j
a_i+a_j>b_i+b_j
ai+aj>bi+bj的数对
<
i
,
j
>
<i,j>
<i,j>的数量。
答案:对a和b按位求差结果保存至c即c=a-b,计算c中
c
i
+
c
j
>
0
c_i+c_j>0
ci+cj>0的数对
<
i
,
j
>
<i,j>
<i,j>的数量。从小到大排序,用lower_bound函数对每个数查找第一个大于当前位置的负数的位置,当前位置与该位置的差值与0的最大值即为当前位置对答案的贡献。复杂度
O
(
n
∗
l
o
g
2
n
)
O(n*log_2n)
O(n∗log2n)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=2e5+10;
ll a[maxn],b[maxn],c[maxn];
int main(){
ll n;
cin>>n;
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(ll i=1;i<=n;i++){
scanf("%lld",&b[i]);
c[i]=a[i]-b[i];
}
sort(c+1,c+1+n);
ll ans=0;
for(ll i=1;i<=n;i++){
ll pos=upper_bound(c+1,c+1+n,-c[i])-c;
ans+=max(0LL,i-pos);
}
cout<<ans<<endl;
}
E Sleeping Schedule
问题:一天h个小时,一个人总共谁n次觉,一次睡一天,第i次可以选择在上一次醒来后
a
i
a_i
ai或
a
i
−
1
a_i-1
ai−1个小时后开始睡,若其睡觉的时间为
[
l
,
r
]
[l,r]
[l,r],则他将拥有一次良好的睡眠,求他最多拥有良好的睡眠次数。
答案:dp求解,dp[i][j]表示前i次睡眠后在第j小时醒来的最多睡眠次数。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[2010][2010];
ll a[2010];
int main(){
ll n,h,l,r;
memset(dp,-1,sizeof(dp));
cin>>n>>h>>l>>r;
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
dp[0][0]=0;
for(ll i=1;i<=n;i++){
for(ll j=0;j<h;j++){
if(dp[i-1][(j-a[i]+h)%h]!=-1){
if(j>=l&&j<=r){
dp[i][j]=max(dp[i][j],dp[i-1][(j-a[i]+h)%h]+1);
}
else{
dp[i][j]=max(dp[i][j],dp[i-1][(j-a[i]+h)%h]);
}
}
if(dp[i-1][(j-a[i]+1+h)%h]!=-1){
if(j>=l&&j<=r){
dp[i][j]=max(dp[i][j],dp[i-1][(j-a[i]+1+h)%h]+1);
}
else{
dp[i][j]=max(dp[i][j],dp[i-1][(j-a[i]+1+h)%h]);
}
}
}
}
ll ans=0;
for(ll i=0;i<h;i++){
ans=max(ans,dp[n][i]);
}
cout<<ans<<endl;
}
F Maximum White Subtree
问题:给一棵树,根不确定,并将树上的每个点染成黑色和白色,求对于每个节点包含这个点的子树中白色点与黑色点的数量差最大为多少?
答案:换根dp,先任取一点为根,做普通的树形dp,u为v的父亲时
c
n
t
[
u
]
+
=
m
a
x
(
0
,
c
n
t
[
v
]
)
cnt[u]+=max(0,cnt[v])
cnt[u]+=max(0,cnt[v])。
之后再进行换根,一个点的答案除了其当前子树的贡献外,还包括不在当前子数中的点对它的贡献,将其父亲消除以这个点为根的字树后求父亲的当前状态,这个状态就是这个点除了字数外的点对其的贡献。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=2e5+10;
ll n;
ll a[maxn];
ll head[maxn];
ll cnt[maxn];
ll ans[maxn];
struct edge{
ll v,next;
}e[maxn<<1];
ll CNT;
void add(ll u,ll v){
e[CNT].v=v;
e[CNT].next=head[u];
head[u]=CNT++;
}
void dfs1(ll u,ll f){
cnt[u]=a[u]?1:-1;
for(ll i=head[u];~i;i=e[i].next){
ll v=e[i].v;
if(v==f)continue;
dfs1(v,u);
cnt[u]+=max(0LL,cnt[v]);
}
}
void dfs2(ll u,ll f){
ans[u]=cnt[u];
for(ll i=head[u];~i;i=e[i].next){
ll v=e[i].v;
if(v==f)continue;
cnt[u]-=max(0LL,cnt[v]);
cnt[v]+=max(0LL,cnt[u]);
dfs2(v,u);
cnt[v]-=max(0LL,cnt[u]);
cnt[u]+=max(0LL,cnt[v]);
}
}
int main(){
memset(head,-1,sizeof(head));
cin>>n;
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(ll i=1;i<n;i++){
ll u,v;
scanf("%lld%lld",&u,&v);
add(u,v);
add(v,u);
}
dfs1(1,-1);
dfs2(1,-1);
for(ll i=1;i<=n;i++){
printf("%lld%c",ans[i],i==n?'\n':' ');
}
}