列表

详情


NC217122. 交通网络

描述

我们的李华去当交警啦!
交通网络呈树状(即n个点,n-1条边),1为根节点,某个时刻,李华可能会接到联络:  
1:联络称某两点之间的道路发生堵塞,使得他们到达这两点之间的点的时间会增加  
2:他们接到了一个紧急任务需要处理,即会在树的某个节点下方增加一个点  
3:他们任务栏中的一个任务已经被完成了,即会删除树的某个节点(保证图始终连通)

输入描述

第一行输入两个数n,m,表示点的个数和接到联络的个数  
第二行输入n个数,表示初始到达第i个点的时间    
接下来n-1行,每行两个数x,y表示x,y之间有一条边  
接下来m行每行一个联络,具体如下  
操作 1: 格式:1 x y k 含义:将x到y的路径上的点每个点的到达时间增加k

操作 2: 格式:2 x y含义:增加一个点,设这是第q次2操作,那么他的编号为n+q,他的初始到达时间为x,他的父亲为y

操作 3: 格式:3 x 含义:删除点x
特别提醒,由于栈大小的原因,请使用迭代层数较小的遍历方式

输出描述

输出若干行,按序号升序排序
每行第一个数表示该点序号,第二个数表示到达当前点需要的时间(只输出目前未被删除的点)

示例1

输入:

6 4
0 0 0 0 0 0
1 2
1 3
2 4
2 5
5 6
1 4 6 1
2 0 5
1 4 7 1
3 6

输出:

1 0
2 2
3 0
4 2
5 2
7 1

说明:

对于30%数据:n,m<=5000
对于另20%数据:保证没有2,3操作
对于另30%数据:保证没有3操作
对于100%数据:n,m<=500000,所有初始到达时间和增加的到达时间<=1000000

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 1298ms, 内存消耗: 210632K, 提交时间: 2023-02-17 21:13:55

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define SET(a,b) memset(a,b,sizeof(a))
#define rep(i,j,k) for(int i=(j);i<=(k);++i)
#define per(i,j,k) for(int i=(j);i>=(k);--i)
int read() {
	int a=0, f=1; char c=getchar();
	while(!isdigit(c)) {
		if(c=='-') f=-1;
		c=getchar();
	}
	while(isdigit(c)) a=a*10+c-'0', c=getchar();
	return a*f;
}
const int N=1e6+5;
int n, m, q, dep[N], w[N], d[N], v[N], f[N][21], pos[N];
int tot, h[N], to[N<<1], nxt[N<<1];
void add(int x,int y) {
	to[++tot]=y, nxt[tot]=h[x], h[x]=tot;
}
void dfs(int x,int fa) {
	dep[x]=dep[fa]+1;
	f[x][0]=fa;
	rep(i,1,20) f[x][i]=f[f[x][i-1]][i-1];
	for(int i=h[x];i;i=nxt[i]) {
		int y=to[i];
		if(y==fa) continue;
		dfs(y,x);
	}
}
int lca(int x,int y) {
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=20;~i;--i) if(dep[y]<=dep[f[x][i]]) x=f[x][i];
	if(x==y) return x;
	for(int i=20;~i;--i) if(f[x][i]!=f[y][i]) x=f[x][i], y=f[y][i];
	return f[x][0];
}
void dfs2(int x,int fa) {
	for(int i=h[x];i;i=nxt[i]) {
		int y=to[i];
		if(y==fa) continue;
		dfs2(y,x);
		d[x]+=d[y];
	}
}
signed main() {
	n=read(), m=read();
	rep(i,1,n) w[i]=read();
	rep(i,1,n-1) {
		int x=read(), y=read();
		add(x,y), add(y,x);
	}
	dfs(1,0);
	while(m--) {
		int op=read();
		if(op==1) {
			int x=read(), y=read(), k=read();
			int z=lca(x,y);
			d[x]+=k, d[y]+=k, d[z]-=k, d[f[z][0]]-=k;
		} else if(op==2) {
			++q;
			int x=read(), y=read();
			w[n+q]=x;
			dep[n+q]=dep[y]+1;
			add(n+q,y), add(y,n+q);
			f[n+q][0]=y;
			rep(i,1,20) f[n+q][i]=f[f[n+q][i-1]][i-1];
		} else {
			int x=read();
			v[x]=1;
		}
	}
	dfs2(1,0);
	rep(i,1,n+q) if(!v[i]) printf("%lld %lld\n",i,w[i]+d[i]);
}

C++(clang++11) 解法, 执行用时: 877ms, 内存消耗: 118156K, 提交时间: 2021-01-31 00:28:42

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+5,T=19;
ll u[N],v[N];int f[N][T+1],d[N],n,m;
bool del[N];
struct edg{int to,nxt;}e[N<<1];int hd[N],cnt;
void add(int x,int y){
	e[++cnt]=(edg){y,hd[x]};hd[x]=cnt;
	e[++cnt]=(edg){x,hd[y]};hd[y]=cnt;
}
void dfs0(int x,int fa){
	d[x]=d[f[x][0]=fa]+1;for(int i=0;i<T;++i)f[x][i+1]=f[f[x][i]][i];
	for(int i=hd[x];i;i=e[i].nxt)if(e[i].to!=fa)dfs0(e[i].to,x);
}
int lca(int x,int y){
	if(d[x]>d[y])swap(x,y);
	for(int i=T;~i;--i)if(d[f[y][i]]>=d[x])y=f[y][i];
	if(x==y)return x;
	for(int i=T;~i;--i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
	return f[x][0];
}
void dfs1(int x,int fa){
	for(int i=hd[x];i;i=e[i].nxt)if(e[i].to!=fa)
		dfs1(e[i].to,x),v[x]+=v[e[i].to];
}
struct lt{int op,x,y,k;}lst[N];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)scanf("%d",&u[i]);
	for(int i=1,x,y;i<n;++i)scanf("%d%d",&x,&y),add(x,y);
	for(int i=0;i<m;++i){
		scanf("%d",&lst[i].op);
		if(lst[i].op==1)scanf("%d%d%d",&lst[i].x,&lst[i].y,&lst[i].k);
		else if(lst[i].op==2)scanf("%d%d",&u[++n],&lst[i].y),add(n,lst[i].y);
		else scanf("%d",&lst[i].x),del[lst[i].x]=true;
	}
	dfs0(1,0);
	for(int i=0;i<m;++i)if(lst[i].op==1){
		int &x=lst[i].x,&y=lst[i].y,&k=lst[i].k;
		v[x]+=k;v[y]+=k;v[x=lca(x,y)]-=k;v[f[x][0]]-=k;
	}
	dfs1(1,1);
	for(int i=1;i<=n;++i)if(!del[i])printf("%d %lld\n",i,u[i]+v[i]);
	return 0;
}

上一题