Codeforces Round 965 (Div. 2) 補題記錄(A,B,D,E1)

yhbqwq發表於2024-08-11

speedforces again~

A < E1 << B < D << C

A

\(k\equiv 1(\bmod2)\),則構造 \((x,y)\)\((x-1,y)\)\((x+1,y)\)\((x-2,y)\)\((x+2,y)\)\(\ldots\)

否則構造 \((x-1,y)\)\((x+1,y)\)\((x-2,y)\)\((x+2,y)\)\(\ldots\)

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int N=1000100;
int a[N];
signed main(){
    int T;cin>>T;
    while(T--){
        int xc,yc,k;
        cin>>xc>>yc>>k;
        if(k&1){
            --k;
            cout<<xc<<' '<<yc<<'\n';
        }
        int x1=xc,y1=yc,x2=xc,y2=yc;
        for(int i=0;i<k;++i,++i){
            --x1,++x2;
            cout<<x1<<' '<<y1<<'\n';
            cout<<x2<<' '<<y2<<'\n';
        }
    }
    return 0;
} // main

B

打表可以得到將原序列位移若干位之後仍然符合條件。因此時間複雜度為 \(O(n)\)

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int N=1000100;
int a[N];
signed main(){
    int T;cin>>T;
    while(T--){
        int xc,yc,k;
        cin>>xc>>yc>>k;
        if(k&1){
            --k;
            cout<<xc<<' '<<yc<<'\n';
        }
        int x1=xc,y1=yc,x2=xc,y2=yc;
        for(int i=0;i<k;++i,++i){
            --x1,++x2;
            cout<<x1<<' '<<y1<<'\n';
            cout<<x2<<' '<<y2<<'\n';
        }
    }
    return 0;
} // main

D

容易發現當且僅當 Elsie 位於 Bessie 從來沒有到過的結點,且透過位於該點的一個次要橋樑可以到達的結點超過了 Bessie。

因此可以建圖跑最短路,找到 Elsie 能夠到達每一個點所需要的最少時間。於是可以列舉每一條備選邊 \(u\to v\),若滿足 \(u<s\) 且 Elsie 到達 \(v\) 的時候 Bessie 沒有到達 \(v\) 那麼就可以獲勝。因此只需要維護不等式 \(v-d_v+1\ge s\) 且還需要滿足 \(u<s\) 即可知道滿足 Elsie 能夠獲勝的所有點。滿足條件的區間即為 \([u+1,v-d_v-1]\),用差分維護一下即可。時間複雜度為 \(O(n)\)(圖為 DAG,可以直接 dp 求解最短路)。

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int N=500100;
vector<int>z[N];int f[N],cf[N];
signed main(){
    int T;cin>>T;
    while(T--){
        int n,m;cin>>n>>m;
        for(int i=1;i<=n;++i)z[i].clear(),cf[i]=0;
        for(int i=1;i<n;++i)z[i].pb(i+1);
        while(m--){
            int a,b;cin>>a>>b;
            z[a].pb(b);
        }
        for(int i=1;i<=n;++i)f[i]=1e18;
        f[1]=0;
        for(int i=1;i<=n;++i)
            for(auto&j:z[i]){
                f[j]=min(f[j],f[i]+1);
                if(i+1<=j-f[j]-1)++cf[i+1],--cf[j-f[j]];
            }
        for(int i=1;i<=n;++i)cf[i]+=cf[i-1];
        for(int i=1;i<n;++i)
            if(cf[i])cout<<"0";
            else cout<<"1";
        cout<<'\n';
    }
    return 0;
} // main

E1

確定不是這個

列舉每一個位置,然後暴力二分向左、右擴充套件。因為每擴充套件一次就會翻倍所以最多隻會二分擴充套件 \(O(\log n)\) 次,因此總的時間複雜度為 \(O(n\log^2n)\)

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int N=200100;
int a[N],s[N];
signed main(){
    // freopen("1.out","w",stdout);
    int T;cin>>T;
    while(T--){
        int n,m;cin>>n>>m;
        for(int i=1;i<=n;++i)cin>>a[i],s[i]=s[i-1]+a[i];
        if(n==1){
            cout<<"1\n";
            continue;
        }
        int cnt=0;
        for(int i=1;i<=n;++i){
            int p=a[i];
            if(i!=1&&a[i]>=a[i-1]||i!=n&&a[i]>=a[i+1]){
                int L=i,R=i,now=a[i];
                while(L!=1||R!=n){
                    if(L!=1&&now>=a[L-1]){
                        int l=1,r=L-1,best=-1;
                        while(l<=r){
                            int mid=l+r>>1;
                            // [mid,L-1] ; now
                            if(now>=s[L-1]-s[mid-1])
                                best=mid,r=mid-1;
                            else
                                l=mid+1;
                        }
                        // cout<<"cf "<<L<<' '<<R<<' '<<best<<'\n';
                        assert(~best);
                        L=best;
                    }else if(R!=n&&now>=a[R+1]){
                        int l=R+1,r=n,best=-1;
                        while(l<=r){
                            int mid=l+r>>1;
                            // [R+1,mid] ; now
                            if(now>=s[mid]-s[R])
                                best=mid,l=mid+1;
                            else
                                r=mid-1;
                        }
                        // cout<<"mm "<<L<<' '<<R<<' '<<best<<'\n';
                        assert(~best);
                        R=best;
                    }else break;
                    now=s[R]-s[L-1];
                }
                if(L==1&&R==n)++cnt;
            }
        }
        cout<<cnt<<'\n';
    }
    return 0;
} // main

相關文章