201912-4 CSP认证 区块链(map + set)

题目思路:

       从考虑时间复杂度入手的话,如果每个更新,都要传遍整个网络,那么就是O(t*n*L)这个复杂度已经很不容乐观了,再乘上常数的话肯可能卡不过去。所以要考虑怎么把时间严格控制在O(t*n*l),我们可以把更新延迟到查询处处理。

       这是我们需要一个vector的数组,v[cur_t][cur_v],表示再cur_t 时刻cur_v这个点的最厉害的那个接受更新链,然后还需要一个Nw[cur_t][cur_v]表示在cur_t时刻,cur_v产生的全部新块。

       怎么处理更新,我们需要一个set数组ch[cur_t]表示cur_t时刻,集合中的点需要更新。

       处理更新的时候,要先v中的和节点记录的链进行更新,再把Nw更新。

       这里需要说的是,如果用上边的做法会发现运行错误只有80,而且空间接近满了,因为set的访问嵌套了一个Nw和v的访问,所以复杂度会多一层log,怎么把这个log去掉,看了大佬博客之后发现,把Nw和v弄成一个数组,所以直接遍历这个数组的就可以了。

这里还有一个疑惑就是,在74行和75行,选用C输出更慢,C++更快,这里不知道为什么,希望睿智的读者能指点一二。

    这个题也是给了很多启发:

          1. 如果不修改容器内容,参数传递一定要用引用类型,或者指针。

          2. 要么全部cin cout 要么全部scanf printf

          3. map的int键值是顺序排放的。

          4. 发现auto遍历容器更快。

以下为80和满分代码。

80:

#include
#define ll long long
using namespace std;
const int MAXN = 1e5+5;
map> >v,Nw;
vectorg[505],ret[505];
map >ch;
int n,m,t,q,cur_t;

bool ck(vector &a,vector &b)
{
    int l1 = a.size();
    int l2 = b.size();
    if(l1 > l2) return 1;
    if (l1 == l2 && a[l1-1] < b[l2-1])
        return 1;
    return 0;
}

void query(int ed_t)
{
    for(auto it:ch){
        int cur_t = it.first;
        if(cur_t>ed_t)break;
        for(auto itt:it.second){
            int to = itt;
            bool f = 0;
            auto &rec=v[cur_t][to],&add=Nw[cur_t][to];
            if( ck(rec,ret[to]) ){
                ret[to] = rec;
                f = 1;
            }
            if(!add.empty()){
                for(auto k:add) ret[to].push_back(k);
                f = 1;
            }
            if(f){
                int len2 = g[to].size();
                for(int j=0;j

满分:

#include
#define ll long long
using namespace std;
const int MAXN = 1e5+5;
map,2>>> v;
vectorg[505],ret[505];
int n,m,t,q;

bool ck(vector& rec,vector &v)
{
	return v.size()==rec.size()?v.back()>rec.back():v.size()ed_t)break;
        for(auto &itt:it.second){
            int to = itt.first;
            bool f = 0;
            //cout<

 

你可能感兴趣的:(201912-4 CSP认证 区块链(map + set))