Acwing第130次周赛

45 阅读4分钟

竞赛 - AcWing

这次周赛题目其实挺不错的,很符合AcwingAcwing周赛惯用的出题风格,第一题睿智到随便谁都能写,后面两题一个是薄纱那些不会算时间复杂度的人,还有一个薄纱所有学的不怎么样的人的。。。

AA66。。。我记得我CC语言期末考试有题就是这个,bbzlbbzl当时好像还有人不会来着。

BB:我做BB的时候情绪不是特别好,导致我其实第一眼就发现这个题是考的前缀和andand枚举yy的值进而在两边遍历相应的xxzz,但是当时可能是肚子疼然后火气很大,我算错了时间复杂度,这个复杂度其实是O(2n2)O(2n^2),但是我想成了O(n3)O(n^3),我当时就寻思这N=5000N=5000怎么过啊,遂放弃,并且开始发puqpuqyxc(bushi)yxc(bushi)。后来结束后一眼发现我估错了时间复杂度,我草了。。。因为分界是yy,故xxzz是绝对独立的,所以只要枚举两次循环而不是两重循环。。。然后就是前缀和把给的那个等式拆分一下,有些细节还是要注意的。比如00的时候数组下标可能变成负数。其他就是按照题意模拟就行了。

CC:这题不看视频我是真不会写。只能说我对图论的理解还是太片面了,然后dfsdfs也是,,,这题用了很巧妙的反证法和猜。我们不妨考虑第一个问题,也就是最大情况,第一个问题我们对所有的无向边都是可以随便走的,那么我们可以直接从起点ss开始dfsdfs,走到有向边我们就直接走,走到无向边,我们看是通过aba-b oror bab-a到的这个点,然后给其赋以正负号。然后我们考虑最小的情况,最小的情况也就是所有的无向边我们都逆着走(你可以想一下怎么逆着走),就是考虑所有有向边能到达的点为一个集合,有向边到不了的点为另一个集合,那么这两个集合之间的路径只可能是两种情况,第一种情况,就是连着反向有向边,第二种情况就是逆向无向边。我们只需要认为规定一下正负就行了,这一点是最难想的。代码实现也有一定难度。

AA

#include <bits/stdc++.h>
using namespace std;
int main(){
    int a,b,c;
    cin>>a>>b>>c;
    int maxn=max(a,b);
    maxn=max(maxn,c);
    int minn=min(a,b);
    minn=min(minn,c);
    cout<<maxn<<" "<<minn;
}

BB:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
map<int,int> mp;
const int N=5010;
int n;
ll s[N],a[N];
void solve(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    s[0]=a[0];
    for(int i=1;i<n;i++){
        s[i]=s[i-1]+a[i];
    }
//  for(int i=0;i<n;i++){
//      cout<<s[i]<<" ";
//  }
    //cout<<endl;
    ll res=-1e18;
    int x0,y0,z0;
    for(int y=0;y<=n;y++){
        ll ans1=-1e18,ans2=-1e18;
        int xx,yy,zz;
        for(int x=0;x<=y;x++){
            ll ansx=0;
            if(x==0) ansx+=0;
            else ansx+=2ll*s[x-1];
            if(y==0) ansx-=0;
            else ansx-=s[y-1];
            if(ans1<ansx){
                ans1=ansx;
                xx=x;
            }
        }
        for(int z=y;z<=n;z++){
            ll ansy=0;
            if(y!=0) ansy-=s[y-1];
            if(z!=0) ansy+=2ll*s[z-1];
            ansy-=s[n-1];
            if(ans2<ansy){
                ans2=ansy;
                zz=z;
            }
        }
        yy=y;
        if(res<ans1+ans2){
            x0=xx,y0=yy,z0=zz;
            res=ans1+ans2;
        }
        //cout<<res<<endl;
    }
    cout<<x0<<" "<<y0<<" "<<z0<<"\n";
}
int main(){
    //IOS;
    solve();
    return 0;
}

CC:

#include <bits/stdc++.h>

#define ll long long

#define x first
#define y second
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr),cout.tie(nullptr);

using namespace std;
const int N=300010,M=2*N;
int e[M],ne[M],w[M],idx=0,h[M],n,m,ans[N],s;
void add(int a,int b,int c){
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
bool st[N];
int dfs(int u,int type){
    int res=1;
    st[u]=true;
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        if(st[j]) continue;
        if(type==0){
            res+=dfs(j,0);
            if(w[i]) ans[abs(w[i])]=w[i];
        }
        else{
            if(!w[i]) res+=dfs(j,1);
            else ans[abs(w[i])]=-w[i];

        }
    }
    return res;
}
int main(){
    IOS;
    memset(h,-1,sizeof h);
    memset(ans,0,sizeof ans);
    cin>>n>>m>>s;
    for(int i=1;i<=m;i++){
        int t,a,b;
        cin>>t>>a>>b;
        if(t==1){
            add(a,b,0);
        }
        else{
            ans[i]=i; 
            add(a,b,i);
            add(b,a,-i);
        }
    }
    memset(st,0,sizeof st);
    cout<<dfs(s,0)<<"\n";
    for(int i=1;i<=m;i++){
    //  cout<<ans[i]<<" ";
        if(ans[i]<0) cout<<"-";
        else if(ans[i]>0) cout<<"+";
    }
    cout<<"\n";
    memset(st,0,sizeof st);
    cout<<dfs(s,1)<<"\n";
    for(int i=1;i<=m;i++){
        //cout<<ans[i]<<" ";
        if(ans[i]<0) cout<<"-";
        else if(ans[i]>0) cout<<"+";
    }
    return 0;
}

下次注意了,别发癫(当题做不出来时候),多找找自己脑子的原因,其实也没有想象中的那么菜。。。