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<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1e5+5;
map<int,unordered_map<int,vector<int>> >v,Nw;
vector<int>g[505],ret[505];
map<int,set<int> >ch;
int n,m,t,q,cur_t;

bool ck(vector<int> &a,vector<int> &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<len2;j++){
                    int x = g[to][j];
                    auto &cn = v[cur_t+t][x];
                    if(ck(ret[to],cn)){
                        cn = ret[to];
                        ch[cur_t+t].insert(x);
                    }
                }
            }
        }
    }
    ch.erase(ch.begin(),ch.upper_bound(ed_t));
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
    }
    scanf("%d%d",&t,&q);
    for(int i=1;i<=n;i++){
        ret[i].push_back(0);
    }
    while(q--)
    {
        int a,b,c;
        scanf("%d%d",&a,&b);
        if(cin.get()=='\n'||cin.eof()) {
            query(b);
            cout<<ret[a].size();
            for(int x:ret[a]){
                cout<<" "<<x;
                //printf(" %d",x);
            }
            printf("\n");
        }
        else
        {
            scanf("%d",&c);
            Nw[b][a].push_back(c);
            ch[b].insert(a);
        }
    }
}
/*

5 10
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
1 27
1 1 1
2 1 2
3 1 3
4 1 4
5 1 5
1 1
2 1
3 1
4 1
5 1
1 2
2 2
3 2
4 2
5 2
1 10 10
2 11 9
1 11
2 11
3 11
4 11
5 11
1 12
2 12
3 12
4 12
5 12
*/

/*

15 13
1 2
2 3
3 4
4 5
1 6
6 7
7 8
8 9
1 10
10 11
11 12
12 13
14 15
6 28
1 1 1
1 2 2
1 6
2 7
13 7
9 7
5 7
3 14
8 14
5 14
11 14
9 25
5 25
13 25
9 29 3
5 29 4
13 29 5
1 53
2 59 6
2 59
1 1000
3 1000
8 1000
9 1000
10 1000
13 1000
14 1000
15 1000
*/

满分:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1e5+5;
map<int,unordered_map<int,array<vector<int>,2>>> v;
vector<int>g[505],ret[505];
int n,m,t,q;

bool ck(vector<int>& rec,vector<int> &v)
{
	return v.size()==rec.size()?v.back()>rec.back():v.size()<rec.size();
}

void query(int ed_t)
{
    for(auto &it:v){
           // cout<<" ** "<<endl;
        int cur_t = it.first;
        if(cur_t>ed_t)break;
        for(auto &itt:it.second){
            int to = itt.first;
            bool f = 0;
            //cout<<cur_t<<" +++ "<<to<<endl;
            auto &rec=itt.second[0],&add=itt.second[1];
            //cout<<" * "<<add.size()<<endl;
            if( ck(rec,ret[to]) ){
                ret[to] = rec;
                f = 1;
            }
            if(add.size()){
                ret[to].insert(ret[to].end(),add.begin(),add.end());
                f = 1;
            }
            if(f){
                for(auto x:g[to]){
                     auto &cn = v[cur_t+t][x][0];
                    if(ck(ret[to],cn)) cn = ret[to];
                }
            }
        }
    }
    v.erase(v.begin(),v.upper_bound(ed_t));
}


int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
    }
    scanf("%d%d",&t,&q);
    for(int i=1;i<=n;i++){
        ret[i].push_back(0);
    }
    getchar();
    while(q--)
    {
        int a,b,c;
        string s ;
        getline(cin,s);
        int len = s.size();
        int tot = 0,cnt = 0,num[5];
        for(int i=0;i<=len;i++){
            if(i == len || s[i] == ' '){
                num[++tot] = cnt;
                cnt = 0;
            }
            else cnt = cnt*10 +(s[i]-'0');
        }
        if(tot == 2){
            query(num[2]);
            cout<<ret[num[1]].size();
            for(int x:ret[num[1]]){
                cout<<" "<<x;
                //printf(" %d",x);
            }
            printf("\n");
        }
        else if(tot == 3){
            v[num[2]][num[1]][1].push_back(num[3]);
        }
    }
}
/*

5 10
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
1 27
1 1 1
2 1 2
3 1 3
4 1 4
5 1 5
1 1
2 1
3 1
4 1
5 1
1 2
2 2
3 2
4 2
5 2
1 10 10
2 11 9
1 11
2 11
3 11
4 11
5 11
1 12
2 12
3 12
4 12
5 12
*/

/*

15 13
1 2
2 3
3 4
4 5
1 6
6 7
7 8
8 9
1 10
10 11
11 12
12 13
14 15
6 28
1 1 1
1 2 2
1 6
2 7
13 7
9 7
5 7
3 14
8 14
5 14
11 14
9 25
5 25
13 25
9 29 3
5 29 4
13 29 5
1 53
2 59 6
2 59
1 1000
3 1000
8 1000
9 1000
10 1000
13 1000
14 1000
15 1000
*/

猜你喜欢

转载自blog.csdn.net/qq_41645482/article/details/105382118