题目思路:
从考虑时间复杂度入手的话,如果每个更新,都要传遍整个网络,那么就是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
*/