Codeforces Round #536 (Div. 2)

https://codeforces.com/contest/1106/problem/A

每次选取一个‘x’ 判断四角是不是’x’

#include <iostream>
#include <fstream>
using namespace std;
char matr[505][505];
bool check(int x,int y)
{
    for(int i=-1; i<2; i++)
        for(int j=-1; j<2; j++)
            if(abs(i)==1&&abs(j)==1)
                if(matr[i+x][j+y]!='X')
                    return false;
    return true;
}
int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=0; i<n; i++)
            cin>>matr[i];
        int ans=0;
        for(int i=0; i<n; i++)
            for(int j=0 ; j<n ; j++)
                if(matr[i][j] == 'X' )
                    if( check(i,j) )
                        ans++;
        cout<<ans<<endl;
    }
}

https://codeforces.com/contest/1106/problem/B

排序

#include <bits/stdc++.h>
using namespace std;
const long long maxn=1e5;
struct node
{
    long long x,y,z;
} arr[maxn],tag[maxn];
bool cmp(node a,node b)
{
    return a.y<b.y;
}
int main()
{
    long long n,m;
    while(cin>>n>>m)
    {
        for(long long i=0; i<n; i++)
        {
            cin>>arr[i].x;
        }
        for(long long i=0; i<n; i++)
        {
            cin>>arr[i].y;
            tag[i].y=arr[i].y;
            tag[i].z=i;
        }
        sort(tag,tag+n,cmp);
        long long mx=0,x,y,s;
        for(long long i=0; i<m; i++)
        {
            cin>>y>>x;
            y--;
            long long ans=0;
            if(arr[y].x < x)
            {
                // cout<<"asd  "<<endl;
                ans+=arr[y].x*arr[y].y;
                x-=arr[y].x;
                arr[y].x=0;
                long long mex;
                if(mx<n)
                {
                    mex=tag[mx].z;
                    while( x>arr[mex].x&&mx<n)
                    {
                        ans+=arr[mex].x*arr[mex].y;
                        x-=arr[mex].x;
                        arr[mex].x=0;
                        mx++;
                        mex=tag[mx].z;
                    }
                    if(mx<n)
                    {
                        ans+=x*arr[mex].y;
                        arr[mex].x-=x;
                        cout<<ans<<endl;
                    }
                    else
                    {
                        mx=n+10;
                        cout<<0<<endl;
                    }
                }
                else
                    cout<<"0"<<endl;
            }
            else
            {
                arr[y].x-=x;
                cout<<arr[y].y*x<<endl;
            }
            // for(long long j=0;j<n;j++)
            //cout<<arr[j].x<<' ';cout<<endl;
        }




    }
}

https://codeforces.com/contest/1106/problem/C

排序- - 大小 不想写
平方和最小 肯定是让每组数的大小尽可能平均 - -。
排序 两两组合就是最优 = = 可以证明。

https://codeforces.com/contest/1106/problem/D

题意 :一个图,每次可以走可以到达的任何一个点,求遍历的最小字典序。

解法:使用set,每次添加可以到达的点,选一个最小的弹出。
set真好用

set的主要功能就是相当于一个插入后能自动排序的数组(从小到大)。但是要注意一个数值在set中只能出现1次或0次
用法:

一.如何定义:

1.注意头文件:#include ;

2.定义set类型的数组:set<类型> 名称;例如—— set s;

  1. (1). insert() ;//插入元素; 例如——s.insert(a);(插入元素a)

    (2) erase() ;//删除排序后的第几个元素;例如——s.erase(a);(删除第a个元素)

                                                                        例如——s.erase(a,b);(删除第a个到第b个元素)
    

    (3). begin() ;//返回set的第一个元素; 例如——a=*s.begin();

    (4). end() ;//返回set的最后一个元素; 例如——a=*s.end();

    (5). clear() ;//清空set内的元素; 例如——a=s.clear();

    (6). empty() ;//判断set内元素是否为空; 例如——a=s.empty();

    (7). max_size() ;//返回set能包含的元素的最大个数; 例如——a=s.max_size();

    (8). size() ;//返回当前元素个数; 例如——a=s.size();

作者:涅槃重塑
来源:CSDN
原文:https://blog.csdn.net/qq_41181881/article/details/81268138
版权声明:本文为博主原创文章,转载请附上博文链接!

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5;
vector<int > tag[maxn];
set<int > nodes;
int pes[maxn];
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        for(int i=0;i<=n;i++)
        {
            pes[i]=0;
            tag[i].clear();
        }
        int x,y;
        for(int i=0;i<m;i++)
        {
            cin>>x>>y;
            tag[x].push_back(y);
            tag[y].push_back(x);
        }

        int q=1;
        nodes.insert(1);
        pes[1]=1;
        while(nodes.size() )
        {
            int son=*nodes.begin();
            nodes.erase(nodes.begin());
            cout<<son<<' ';
            q++;
            for(int i=0;i<tag[son].size(); i++)
            {
                int se=tag[son][i];
                if(!pes[se])
                {
                    pes[se]=1;
                    nodes.insert(se);
                }
            }
        }
        cout<<endl;

    }
}

https://codeforces.com/contest/1106/problem/E

题意:
在长度为n的时间轴上,有k个红包,每个红包有领取时间段[s,t],价值w,以及领了个这个红包之后,在时间d到来之前无法再进行领取操作。每次领取的策略是取当前可领取红包中w最大的,w相同时取d最大的。再给m个干扰机会,一个干扰机会可以使其在任意一个x这个时间点无法进行领取操作直到x+1。问最优使用不超过m次干扰下,将领取的最小红包价值总和。(n,k<=1e5,m<=200)

dp(i,j) i位置被打扰了j次能获得的最少硬币
预处理:寻找每个时刻所要选取的红包。 使用multiset 作为容器 每个时刻添加红包,然后结尾时刻删除红包。

之后对每个时刻dp 此时刻是否阻止选择红包。每次选择最小值。
跑记忆化搜索dfs.
最后的结果就是最小值。

#include <bits/stdc++.h>
using namespace std;
const long long maxn=1e5+5;

//in 为可选红包,out为不可选红包
vector< pair <int,long long > > in[maxn],out[maxn];

//代表每个时刻的最佳红包
pair<int,long long > best[maxn];

//dp(i,j) i位置被打扰了j次能获得的最少硬币
long long dp[maxn][205];

//寻找best的临时set容器
multiset<pair <int,long long > > now;
long long n,m,k;


void tclear()
{
    memset(dp,-1,sizeof(dp));
    for(long long i=0; i<=n+1; i++)
        in[i].clear(),out[i].clear();
}


long long dfs(long long place, long long  c)
{
    if(place >n )
        return 0;
    if(dp[place][c]>=0)
        return dp[place][c];
    long long res=best[place].first+dfs(best[place].second+1,c);
    if(c<m)
        res=min(res,dfs(place+1,c+1));
    return dp[place][c]=res;
}
int main()
{

    while(cin>>n>>m>>k)
    {
        tclear();
        long long l,r,d,w;
        for(long long i=0; i<k; i++)
        {
            cin>>l>>r>>d>>w;
            in[l].push_back(make_pair(w,d) );
            out[r+1].push_back(make_pair(w,d) );
        }

        for(long long i=1; i<=n+1; i++)
        {
            for(long long j=0; j<in[i].size(); j++)
                now.insert(in[i][j]); //加入可以领取的红包
            for(long long j=0; j<out[i].size(); j++)
                now.erase( now.find(out[i][j]) );//去掉不可取的,去掉单个不可取。如果now.erase(out[i][j]) 则删除所有相同的out[i][j];
            if(now.size() )
                best[i]=*now.rbegin();//选择最佳策略
            else
                best[i]= {(long long )0,(long long) i};
        }

        cout<<dfs(1,0)<<endl;


    }

}

所以 multiset 嵌套pair 应该是 首先按照first 然后按照second排序
代码等同于

#include <bits/stdc++.h>
using namespace std;
const int maxn= 1e5+5;

struct node
{
    int first,second;
    //node(){}
    node(int xx=0,int yy=0)
    {
        first=xx;
        second=yy;
    }

};

struct cmp
{
    bool operator () (const node &a, const node &b)
    {
        if(a.first!=b.first)
            return a.first<b.first;
        else
            return a.second<b.second;
    }
};

//in 为可选红包,out为不可选红包
vector<node > in[maxn],out[maxn];

//代表每个时刻的最佳红包
node best[maxn];

//dp(i,j) i位置被打扰了j次能获得的最少硬币
long long dp[maxn][205];

//寻找best的临时set容器
multiset<node,cmp > now;
long long n,m,k;


void tclear()
{
    memset(dp,-1,sizeof(dp));
    for(long long i=0; i<=n+1; i++)
        in[i].clear(),out[i].clear();
}


long long dfs(long long place, long long  c)
{
    if(place >n )
        return 0;
    if(dp[place][c]>=0)
        return dp[place][c];
    long long res=best[place].first+dfs(best[place].second+1,c);
    if(c<m)
        res=min(res,dfs(place+1,c+1));
    return dp[place][c]=res;
}
int main()
{

    while(cin>>n>>m>>k)
    {
        tclear();
        long long l,r,d,w;
        for(long long i=0; i<k; i++)
        {
            cin>>l>>r>>d>>w;
            in[l].push_back(node(w,d) );
            out[r+1].push_back(node(w,d) );
        }

        for(long long i=1; i<=n+1; i++)
        {
            for(long long j=0; j<in[i].size(); j++)
                now.insert(in[i][j]); //加入可以领取的红包
            for(long long j=0; j<out[i].size(); j++)
                now.erase( now.find(out[i][j]) );//去掉不可取的,去掉单个不可取。如果now.erase(out[i][j]) 则删除所有相同的out[i][j];
            if(now.size() )
                best[i]=*now.rbegin();//选择最佳策略
            else
                best[i]= {(long long )0,(long long) i};
        }

        cout<<dfs(1,0)<<endl;


    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值