Codeforces Round 982 (Div. 2)

zhouruoheng發表於2024-10-30

Codeforces Round 982 (Div. 2) 總結

A

猜結論,最後的圖形的周長都能移成一個長方形的周長,這個長方形就是 \(w\)\(h\) 的最大值。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=1;
int n;
int w,h;
int x,y;
void solve()
{
    x=y=0;
    cin>>n;
    for(int i=1;i<=n;i++) 
    {
        cin>>w>>h;
        x=max(x,w),y=max(y,h);
    }
    cout<<2*(x+y)<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

B

首先,Stalin Sort 後的結果是會產生單調不下降。對於 \(a_i\),要保留 \(a_i\) 的話,\(a_i\) 前面不能有數,且後面不能有大於 \(a_i\) 的數。列舉 \(a_i\) 分別計算要刪去的數,複雜度為 \(O(n^2)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2005;
int n;
int a[N];
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int ans=n;
    for(int i=1;i<=n;i++)
    {
        int cnt=i-1;
        for(int j=i+1;j<=n;j++) cnt+=(a[j]>a[i]);
        ans=min(ans,cnt);
    }
    cout<<ans<<'\n';
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

C

轉化一下條件,若有 \(1 \le i \le n\)\(a_i+i-1=|a|\),調整大小為 \(a_i+i-1+i-1\)。可以用 dfs,用 map 標記是否搜過,這樣每個值最多進去搜尋一次,出去一次,複雜度為 \(O(n)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map> 

using namespace std;
typedef long long ll;
const int N=3e5+5;
int n;
ll a[N];
ll ans;
typedef pair<ll,int> PLI;
PLI b[N];
#define fi first 
#define se second 
map<ll,bool> H;
void dfs(ll siz)
{
    if(H.count(siz)) return ;
    H[siz]=1;
    ans=max(ans,siz);
    if(siz>b[n].fi) return ;
    PLI tmp={siz,0};
    int l=lower_bound(b+1,b+n+1,tmp)-b;
    tmp.se=n;
    int r=upper_bound(b+1,b+n+1,tmp)-b-1;
    for(int i=l;i<=r;i++)
    {
        if(b[i].se==0) continue;
        dfs(siz+b[i].se);
    }
}
void solve()
{
    H.clear();
    cin>>n;
    ans=n;
    for(int i=1;i<=n;i++) cin>>a[i],b[i]={a[i]+i-1,i-1};
    sort(b+1,b+n+1);
    dfs(n);
    cout<<ans<<'\n';
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

D1

觀察到詭異的資料範圍 \(nm \le 3e5\),不難想到應該是個 \(O(nm)\) 的解法。

考慮 dp。設 \(f_{i,j}\)\(k\) 的值為 \(i\) 時,\(a\) 剩下的第一個元素的下標為 \(j\) 的最小代價。

  • 操作一:\(j\) 不變,\(i\) 變為 \(i+1\),則有 \(f_{i+1,j}=\min{f_{i,j}}\)
  • 操作二:查詢第一個位置 \(c\) 滿足 \(\sum_{t=i}^c a_t > b_i\),則有 \(f_{i,c}=\min{f_{i,j}+m-i}\)

答案就是 \(\min_{i=1}^m f_{i,n+1}\)

然後因為 \(n,m \le 3e5\),不好開陣列,所以要麼用 vector,要麼用滾動陣列。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=3e5+5;
const ll inf=1e18;
int n,m;
ll a[N],b[N];
ll f[2][N];
ll ans=inf;
void solve()
{
    ans=inf;
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i],a[i]+=a[i-1];
    for(int i=1;i<=m;i++) cin>>b[i];
    for(int j=1;j<=n+1;j++) f[1][j]=inf;
    f[1][1]=0;
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n+1;j++) f[i+1&1][j]=inf;
        for(int j=1;j<=n;j++)
        {
            int k=upper_bound(a+j,a+n+1,b[i]+a[j-1])-a;
            if(k>j) f[i&1][k]=min(f[i&1][k],f[i&1][j]+m-i);
            f[i+1&1][j]=min(f[i+1&1][j],f[i&1][j]);
        }
        ans=min(ans,f[i&1][n+1]);
    }
    cout<<(ans==inf ? -1 : ans)<<'\n';
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

相關文章