3.25-3.31周报

天梯赛2

7-10 红色警报

这道题的题意要注意是删去一个城市后增加了多少个区域,而不是有多少个城市变成了单独的点,赛时理解错了题意,用set做会有点有问题。其实很简单,就是bfs搜一下有多少个联通块,每次删除把被删的点打个标记,每次联通块的个数和上一次的比较一下,只要增加就是改变了连通性,这样判断可以规避掉一开始就只有一个点单独是一个联通块的情况。

点击查看代码
void solve() {
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    int ans;
    memset(vis,0,sizeof(vis));
    ans=0;
    for(int j=0;j<n;j++){
        if(vis[j]==1)
            continue;
        vis[j]=1;
        q.push(j);
        while(!q.empty()){
            auto x=q.front();
            q.pop();
            for(auto e:g[x]){
                if(vis[e])
                    continue;
                vis[e]=1;
                q.push(e);
            }
        }
        ans++;
    }
    //cout<<ans<<endl;
    int k;
    cin>>k;
    int ans1;
    for(int i=1;i<=k;i++){
        int d;
        cin>>d;
        f[d]=1;
        memset(vis,0,sizeof(vis));
        ans1=0;
        for(int j=0;j<n;j++){
            if(vis[j])
                continue;
            if(f[j])
                continue;
            vis[j]=1;
            q.push(j);
            while(!q.empty()){
                auto x=q.front();
                q.pop();
                for(auto e:g[x]){
                    if(vis[e])
                        continue;
                    if(f[e])
                        continue;
                    vis[e]=1;
                    q.push(e);
                }
            }
            ans1++;
        }
        //cout<<ans1<<endl;
        if(ans1>ans){
            cout<<"Red Alert: City "<<d<<" is lost!\n";
        }
        else{
            cout<<"City "<<d<<" is lost.\n";
        }
        ans=ans1;
    }
    if(k==n){
        cout<<"Game Over.\n";
    }
    return ;
}

7-15 特殊堆栈

这道题就是对顶堆,题意要中间的那个值,那就左右各开一个multiset,我只要保证左边的数量最多比右边多一个,要不就相等,那此时左边的最后一个数就是结果。要注意multiset的语法规则,erase函数删除某个数的话是把所有的都删了,应该先用find函数找到它的位置再删,erase函数也不能删去rbegin要用end的prev

点击查看代码
void tz(){
    int x1,x2;
    x1=s1.size(),x2=s2.size();
    if (x2 - x1 > 0) {
        int e = *(s2.begin());
        s2.erase(s2.begin());
        s1.insert(e);
    }
    if (x1 - x2 > 1) {
        int e = *(s1.rbegin());
        s1.erase(prev(s1.end()));
        s2.insert(e);
    }
    return ;
}

void solve() {
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        string s;
        cin>>s;
        if(s=="Push"){
            int x;
            cin>>x;
            q.push(x);
            if(s1.empty()){
                s1.insert(x);
            }
            else {
                if (x >= *(s1.rbegin())) {
                    s2.insert(x);
                }
                else {
                    s1.insert(x);
                }
            }
            tz();
        }
        else if(s=="Pop"){
            if(q.empty()){
                cout<<"Invalid\n";
                continue;
            }
            int x=q.top();
            q.pop();
            cout<<x<<endl;
            //cout<<s1.size()<<" "<<s2.size()<<endl;
            //int e=*(s1.rbegin());
            auto ee=s1.find(x);
            if(ee!=s1.end()){
                s1.erase(ee);
            }
            else{
                s2.erase(s2.find(x));
            }
            tz();
        }
        else{
            if(q.empty()){
                cout<<"Invalid\n";
                continue;
            }
            cout<<*(s1.rbegin())<<endl;
        }

    }
    return ;
}

天梯赛3

7-7 连续因子

这道题其实就是暴力,因为要找连续因子,那不就是暴力循环起点,然后暴力向后循环,要注意第一维只要找到sqrt(n)就可以了,但是第二维不行,不过第二维最多12个,也无所谓。要注意本身是素数的情况。那就是全跑完了都没找到因子。

点击查看代码
void solve() {
    int n;
    cin>>n;
    int dans=0;
    int max1=0,l,d;
    
    for(int i=2;i*i<=n;i++){
        int x=n;
        int ans=0;
        if(x%i==0){
            ans++;
            x/=i;
            for(int j=i+1;j<=n;j++){
                if(x%j==0){
                    ans++;
                    x/=j;
                }
                else{
                    break;
                }
            }
            if(ans>max1){
                max1=ans;
                //dans=1;
                l=i;
            }
//            else if(ans==max1){
//                //dans++;
//            }
        }
    }
    if(max1==0){
        cout<<1<<endl;
        cout<<n<<endl;
        return ;
    }
    cout<<max1<<endl;
    for(int i=l;i<=l+max1-1;i++){
        cout<<i;
        if(i!=l+max1-1){
            cout<<"*";
        }
        else{
            cout<<"\n";
        }
    }
    return ;
}

7-9 哈利波特的考试

这道题一眼弗洛伊德,但怎么会有人把板子敲错啊。。。

就是纯板子题,不放代码了。

7-11 病毒溯源

这道题我一看题面感觉很像并查集,因为保证了每个病毒都是由唯一的病毒变异而来,我就想着从每一个点开始去找祖先,看看谁最长,但是这个做法很暴力,直接运行超时,其实反过来想,这就是个树啊,找最长链,那就是找到树的根节点,然后计算每一个节点的深度。

点击查看代码
void dfs(int x){
    if(dp[x]>max1){
        max1=dp[x];
        dd=x;
    }
    for(auto e:g[x]){
        dp[e]=dp[x]+1;
        dfs(e);
    }
}
void solve() {
    int n;
    cin>>n;
    for (int i = 0;i < n;i++){
        fa[i] = i;
    }
    for(int i=0;i<n;i++){
        int k;
        cin>>k;
        for(int j=1;j<=k;j++){
            int x;
            cin>>x;
            g[i].push_back(x);
            fa[x]=i;
        }
        sort(g[i].begin(),g[i].end());
    }
    int d;
    for(int i=0;i<n;i++){
        if(fa[i]==i){
            d=i;
            break;
        }
    }
    dp[d]=1;
    dfs(d);
    //cout<<d<<" "<<dd<<endl;
    vector<int>ve;
    while(1){
        if(dd==fa[dd])
            break;
        ve.push_back(dd);
        dd=fa[dd];
    }
    ve.push_back(d);
    int x=ve.size();
    cout<<x<<endl;
    for(int i=x-1;i>=0;i--){
        cout<<ve[i];
        if(i!=0){
            cout<<" ";
        }
        else{
            cout<<endl;
        }
    }
    return;
}

训练1

7-1 拯救007

这道题就是有一个正方形的池子,里面有一个圆形的台子,从圆形的台子到池子的边上有很多鳄鱼,可以从台子跳到这些鳄鱼点再到池子边上,这个圆形台子很好想了,从台子的圆心开始跳,dfs搜的时候就要注意,要是是从圆心出发的就是距离+半径,判断这个点能不能到达池子的边时要注意,到边上的最短距离一定是垂直于池子的边。

点击查看代码
double get(int x,int y){
    return sqrt((a[x].x-a[y].x)*(a[x].x-a[y].x)+(a[x].y-a[y].y)*(a[x].y-a[y].y));
}
void dfs(int x){
    vis[x]=1;
    if(f==1)
        return ;
    if(a[x].x-d<=-50||a[x].x+d>=50||a[x].y-d<=-50||a[x].y+d>=50){
        f=1;
        return ;
    }
    if(x==0){
        for(int i=1;i<=n;i++){
            if(vis[i])
                continue;
            double jl=get(i,x);
            if(jl<=(7.5+(double)d)){
                dfs(i);
            }
        }
    }
    else{
        for(int i=1;i<=n;i++){
            if(vis[i])
                continue;
            double jl=get(i,x);
            if(jl<=(double)(d)){
                dfs(i);
            }
        }
    }
}
void solve() {

    cin>>n>>d;
    a[0].x=0,a[0].y=0;
    for(int i=1;i<=n;i++){
        cin>>a[i].x>>a[i].y;
    }
    vis[0]=1;
    dfs(0);
    if(f==1){
        cout<<"Yes\n";
    }
    else{
        cout<<"No\n";
    }
    return ;
}

训练2

25分的题都做完了,30分的还没开始补。

Codeforces 937 (Div.4)

这套题就补了一下EF,G好像是个状压dp还没补。

算法学习

这周开始补字符串不会的算法
字符串算法

posted @ 2024-03-31 12:44  zyzzzzlh  阅读(37)  评论(0)    收藏  举报