Codeforces Round #722 (Div. 2)

Codeforces Round #722 (Div. 2)

B. Sifid and Strange Subsequences

题目链接

思路:

题目要求子序列两两之间的值全部大于等于MAX,不妨给序列排序。

排序后,对于序列,只需在意相邻是数是否大于等于MAX。

很容易看出,所有非正数都是满足的,现在对多能加入一个正数,选最小的正数看是否比原先答案更优。

代码实现:

#include <iostream>
#include <set>
using namespace std;
const int N=1e5+7;
int t;
int n,a[N];
set <int> sa;
int dfs(int p,int mx){
    auto it=sa.upper_bound(p-mx);
    int ans=0;
    if(it==sa.begin()){
        return 1;
    }else{
        it--;
        ans=dfs(*it,mx)+1;
    }
    return ans;
}
int main(){
    cin>>t;
    while(t--){
        cin>>n;
        sa.clear();
        int ans=0;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            sa.insert(a[i]);
            if(a[i]<=0) ans++;
        }
        for(auto i=sa.begin();i!=sa.end();i++){
            if(*i>0){
                ans=max(ans,dfs(*i,*i));
                break;
            }
        }
        cout<<ans<<endl;
    }
}


C. Parsa’s Humongous Tree

题目链接

思路:

结论:

可以得出,结点的值只可能取 l i , r i l_i,r_i li,ri两种(证明不会,打草稿猜测出来的)。

树形dp:

f l [ u ] 为 u fl[u]为u fl[u]u节点的值为 l u l_u lu的答案。

f r [ u ] 为 u fr[u]为u fr[u]u节点的值为 r u 的 答 案 r_u的答案 ru

状态转移方程为:

f l [ u ] + = m a x ( f l [ v ] + a b s ( l [ u ] − l [ v ] ) , f r [ v ] + a b s ( l [ u ] − r [ v ] ) ) fl[u]+=max(fl[v]+abs(l[u]-l[v]),fr[v]+abs(l[u]-r[v])) fl[u]+=max(fl[v]+abs(l[u]l[v]),fr[v]+abs(l[u]r[v]))

f r [ u ] + = m a x ( f l [ v ] + a b s ( r [ u ] − l [ v ] ) , f r [ v ] + a b s ( r [ u ] − r [ v ] ) ) fr[u]+=max(fl[v]+abs(r[u]-l[v]),fr[v]+abs(r[u]-r[v])) fr[u]+=max(fl[v]+abs(r[u]l[v]),fr[v]+abs(r[u]r[v]))

代码实现:

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=1e5+7;
struct node{
    ll l,r;
}a[N];
int t,n;
ll fl[N],fr[N];
vector <int> ho[N];
void dfs(int p,int fa){
    for(int i=0;i<ho[p].size();i++){
        int v=ho[p][i];
        if(v==fa) continue;
        dfs(v,p);
        fl[p]+=max(fr[v]+abs(a[p].l-a[v].r),fl[v]+abs(a[p].l-a[v].l));
        fr[p]+=max(fr[v]+abs(a[p].r-a[v].r),fl[v]+abs(a[p].r-a[v].l));
    }
}
void init(){
    for(int i=0;i<=n+1;i++){
        ho[i].clear();
        fl[i]=fr[i]=0;
    }
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        init();
        for(int i=1;i<=n;i++){
            scanf("%lld %lld",&a[i].l,&a[i].r);
        }
        for(int i=1;i<=n-1;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            ho[u].push_back(v);
            ho[v].push_back(u);
        }
        dfs(1,-1);
        printf("%lld\n",max(fl[1],fr[1]));
    }
}

D. Kavi on Pairing Duty

题目链接

思路:

符合题意的可分为两种:

  1. 线段不覆盖,且所有线段相等

  2. 线段存在覆盖

存在覆盖的线段可被1,2…i-1覆盖,即可得

f [ i ] = ∑ j = 1 j = i − 1 f [ j ] f[i]=\sum_{j=1}^{j=i-1}f[j] f[i]=j=1j=i1f[j]

不被覆盖的为 i i i的因子数。

代码实现:

#include <iostream>
using namespace std;
typedef long long ll;
const int N=1e6+7;
const ll mod=998244353;
int n;
ll f[N],count[N];
int main(){
    scanf("%d",&n);
    f[1]=1,f[2]=3;
    ll sum=4;
    for(int i=1;i<=n;i++ ) 
        for(int j=i;j<=n;j+=i) 
            count[j]++;
    for(int i=3;i<=n;i++){
        f[i]=(sum+count[i])%mod;
        sum=(sum+f[i])%mod;
    }
    printf("%lld\n",f[n]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值