首页 > 其他分享 >CF1856

CF1856

时间:2024-11-02 15:57:44浏览次数:1  
标签:CF1856 return int ll mxn ans define

总结

\(t1\) 看起来好简单啊,\(5min\) 切了。
\(t2\) 看起来好简单啊,\(15min\) 切了。
\(t3\) 看起来好难啊,\(50min\) 跳了。
一开始想到了二分答案,迟迟想不到 \(O(n)\) 的 \(check\),于是思维开始发散,从贪心想到 \(dp\)。
考完发现大家都是 \(O(n^2)\) 的 \(check\),wssb。
\(t4\) 是道交互,直接跳了。
\(t5\) 看起来还行,让我做做。
\(after\ 1\ hour......\)
还是没想出来,还差一个 \(dp\) 就想出来了,但就是抓不到方程。。。
比赛结束前 \(5min\) 想到了做法,可惜大势已去。。。
只做出来两道题,太惨了。
实力太菜导致的。
(考后两分钟交了 \(t5\) 并 \(AC\))

解析

A. Tales of a Sort

难度:红
简单题。


#include<bits/stdc++.h>
#define mxn 55
#define ll long long
using namespace std;
ll t,n,a[mxn],ans;
void solve(){
    cin>>n;ans=0;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<n;i++)
        if(a[i]>a[i+1])ans=max(ans,a[i]);
    cout<<ans<<'\n';
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>t;while(t--)solve();
    return 0;
}

B. Good Arrays

难度:橙
如果不是 \(1\) 对其他数的贡献为 \(a_i-1\),是 \(1\) 贡献为 \(-1\)。
最后判断贡献是否 \(<0\) 就行了。


#include<bits/stdc++.h>
#define mxn 100010
#define ll long long
using namespace std;
ll t,n,a[mxn],sum;
void solve(){
    cin>>n;sum=0;
    for(int i=1;i<=n;i++)cin>>a[i];
    if(n==1){cout<<"NO\n";return;}
    for(int i=1;i<=n;i++){
        if(a[i]==1)sum--;
        else sum+=a[i]-1;
    }
    if(sum<0)cout<<"NO\n";
    else cout<<"YES\n";
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>t;while(t--)solve();
    return 0;
}

C. To Become Max

难度:黄-绿
想着用二分,结果 \(O(n)\) 的 \(check\),结果很久都没写出来,玉玉了。
打完才发现 \(check\) 是可以 \(O(n^2)\) 的。


#include<bits/stdc++.h>
#define mxn 1010
#define ll long long
using namespace std;
ll n,k,t,a[mxn];
ll l,r,ans;
ll tot,b[mxn];
bool flg=1;
bool check(ll x){
    if(a[n]>=x)return 1;
    for(int i=1;i<n;i++){
        if(a[i]>=x)return 1;
        tot=k,flg=1;
        for(int j=1;j<=n;j++)b[j]=a[j];
        tot-=x-b[i],b[i]=x;
        if(tot<0)continue;
        for(int j=i+1;j<n;j++){
            if(b[j]>=b[j-1]-1)return 1;
            tot-=(b[j-1]-1)-b[j];
            b[j]=b[j-1]-1;
            if(tot<0){
                flg=0;break;
            }
        }
        if(flg&&b[n]>=b[n-1]-1)return 1;
    }
    return 0;
}
void solve(){
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>a[i];
    l=1,r=1e12;
    while(l<=r){
        ll mid=(l+r)>>1;
        if(check(mid))ans=mid,l=mid+1;
        else r=mid-1;
    }
    cout<<ans<<'\n';
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>t;while(t--)solve();
    return 0;
}

D. More Wrong

难度:绿
发掘一下最大值的性质!如果最大值位置为 \(p\),则有 \(ask(l,p)=ask(l,p-1)\)。
因为找不到比 \(a_p\) 更大的数了。
所以可以分治查找。复杂度 \(O(4n^2)\)。


#include<bits/stdc++.h>
#define mxn 5010
#define pb push_back
using namespace std;
int n,t;
int ask(int l,int r){
    cout<<"? "<<l<<' '<<r<<endl;
    int ret;cin>>ret;return ret;
}
int dfs(int l,int r){
    if(l==r)return l;
    if(l==r-1)return ask(l,r)?l:r;
    int mid=(l+r)>>1,x=dfs(l,mid),y=dfs(mid+1,r);
    if(ask(l,y-1)==ask(l,y))return y;
    else return x;
}
void solve(){
    cin>>n;
    int ans=dfs(1,n);
    cout<<"! "<<ans<<endl;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>t;while(t--)solve();
    return 0;
}

E1. PermuTree (easy version)

难度:绿
题目转化一下:在以 \(i\) 为根的树下选取若干子树分成两部分,使子树大小的和的乘积最大。
数据较小的时候直接暴力背包就行了。


#include<bits/stdc++.h>
#define mxn 5010
#define pb push_back
#define ll long long
using namespace std;
ll n,k,a[mxn];
ll dp[mxn],sze[mxn],ans;
vector<int> t[mxn];
void solve(){
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>a[i];
}
void dfs1(int u,int f){
    sze[u]=1;
    for(int i=0;i<t[u].size();i++){
        int v=t[u][i];
        if(v==f)continue;
        dfs1(v,u);
        sze[u]+=sze[v];
    }
    return;
}
void dfs2(int u,int f){
    ll cnt=0,sum=0,maxn=0,vis[mxn]={0};
    vis[0]=1;
    for(int i=0;i<t[u].size();i++){
        int v=t[u][i];
        if(v==f)continue;
        dfs2(v,u);
        for(int j=sze[u];j>=0;j--)
            if(vis[j]){
                vis[j+sze[v]]=1;
                maxn=max(maxn,(j+sze[v])*(sze[u]-1-j-sze[v]));
            }
    }
    ans+=maxn;
    return;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1+1;i<=n;i++){
        int v;cin>>v;
        t[i].pb(v),t[v].pb(i);
    }
    dfs1(1,0);
    dfs2(1,0);
    cout<<ans;
    return 0;
}

E2. PermuTree (hard version)

难度:紫
我们发现,求出时间复杂度的瓶颈在于:
把儿子大小构成的数集合分成差尽可能小的两部分。
对于这里的优化,有很多做法,如 \(FTT\),\(bitset\),这里选择 \(bitset\) 的做法。
代码先咕着。

标签:CF1856,return,int,ll,mxn,ans,define
From: https://www.cnblogs.com/nagato--yuki/p/18521736

相关文章

  • CF1856E1 PermuTree (easy version) 题解
    假定当前在节点\(u\),它拥有两棵子树\(v,w\),此时\(u\)是\(\operatorname{lca}(v,w)\)。我们一定可以构造出一个排列\(a\),使得所有满足\(i\inv\)的节点\(i\)和满足\(j\inw\)的节点\(j\),有\(a_i<a_u<a_j\)。因此此时点\(u\)对于答案的贡献即为\(size_v\times......
  • cf1856E2. PermuTree (hard version)(bitset+二进制优化背包+开不同大小bitset)
    https://codeforces.com/contest/1856/problem/E2结论是显然的,关键是有一些科技在里面bitset+二进制优化具体分析可以参考https://codeforces.com/blog/entry/98663简而言之就是可以通过\(O(\frac{C\sqrtC}{w})\)的复杂度判断是否能够获得某种体积开不同大小bitsettemplate......
  • CF1856B Good Arrays
    题意简述:给定一个序列\(a\),我们定义一个序列\(b\)是好的当且仅当对于\(1\dotsn\)内的每一个\(i\),\(a_i\neqb_i\)且\(\sum_{i=1}^na_i=\sum_{i=1}^nb_i\)(\(a_i\),\(b_i\)均为正整数)。现在有\(T\)组数据,每组数据给定\(n\)和序列\(a\),判断是否存在一个合法的序......
  • 【题解】Codeforces Round 890(CF1856)
    赛时过了A-E1,rk195可惜是E2傻逼了不会背包优化了,直接连普及组水平都不到了。A.TalesofaSort题目描述:给定长度为\(n\)的序列\(a\),每次操作为对于所有\(i\)将\(a_i\)变为\(\max(a_i-1,0)\),询问最少多少次操作之后可以让序列\(a\)单调不降。题目分析:唯一能改变......
  • CF1856B
    原题翻译引理1:在\([l,r]\)内一定存在一个数\(x\)使满足\((r-l+1)|x\)证明:设\(k=r-l+1\),则\([l,r]\)内所有数都可以写成\(pk+q(0\leqq<k)\)的形式,且一定互不相同。根据抽屉原理即可证得结论。知道这个结论后我们就可以发现对于区间\([l,r]\)的某个整数,都可以在\([1,x]\)内......