hdu5957 ICPC-2016 沈阳 I bfs序+线段树+分类讨论

题面

思路:
用线段树维护bfs序,因为同一层的儿子的bfs序连续

很久没有写过分类讨论了
细节错误很多:
1. k == 2时要判在不在环上,环够不够长,fa[x]在不在环上
2. bfs序只保证所有儿子在连续区间,而层与层之间是不连续的。开始竟然天真的以为是连续的
调了 1h多 还写了 30多min 代码能力要加强!

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define repd(i,a,b) for(int i=a;i>=b;--i)
#define rvc(i,S) for(int i=0;i<(int)S.size();++i)
#define fore(i,x) for(int i = head[x] ; i ; i = e[i].next)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) (x&(-x))
using namespace std;
#define maxn 100020

typedef long long ll;
int n,T,m;
struct node{
	int next,to;
}e[maxn * 2];
int head[maxn],cnt,tag[maxn],a[maxn],tot,pre[maxn],post[maxn],fa[maxn];
int l[maxn],r[maxn],dfn[maxn],q[maxn],hh,tt,times,l2[maxn],r2[maxn];
int st[maxn],tops,vis[maxn],bl;
ll sum[maxn << 2],add[maxn << 2];
char ch[20];

void clear(){
	rep(i,1,n){
	   	head[i] = tag[i] = fa[i] = post[i] = pre[i] = dfn[i] = vis[i] = 0;
	}
	rep(i,1,n << 2){
		sum[i] = add[i] = 0;
	}
	times = tops = bl = tt = hh = cnt = tot = 0;
}
inline void adde(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}
void dfs(int x,int fa){
	if ( vis[x] ){
		while ( st[tops] != x ){
			a[++tot] = st[tops--], 	tag[a[tot]] = 1;
		}
		a[++tot] = x , tag[x] = 1;
		bl = 1;
		return;
	}
	vis[x] = 1 , st[++tops] = x;
	fore(i,x){
		if ( e[i].to == fa ) continue;
		dfs(e[i].to,x);
		if (  bl ) return;
	}
	tops--;
}
void bfs(int x){
	tt = hh = 0;
	q[tt++] = x;
	dfn[x] = ++times;
	while ( hh < tt ){
		int x = q[hh++];
		fore(i,x){
			if ( !tag[e[i].to] && !dfn[e[i].to] ){
				dfn[e[i].to] = ++times;
				fa[e[i].to] = x;
				q[tt++] = e[i].to;
			}
		}
	}
	repd(i,tt - 1,0){
		int x = q[i];
		l[x] = l2[x] = n , r[x] = r2[x] = 0;
		fore(j,x){
			if ( !tag[e[j].to] && fa[e[j].to] == x ){
				r[x] = max(r[x],dfn[e[j].to]);
				r2[x] = max(r2[x],r[e[j].to]);
				l[x] = min(l[x],dfn[e[j].to]);
				l2[x] = min(l2[x],l[e[j].to]);
			}
		}
	}
}
void init(){
	//find_circle
	dfs(1,0);
	a[0] = a[tot] , a[tot + 1] = a[1];
	rep(i,1,tot){
		int x = a[i];
		pre[x] = a[i - 1];
		post[x] = a[i + 1];
		bfs(x);
		if ( l[x] > r[x] ) l[x] = dfn[x] + 1,r[x] = dfn[x];
	}
		
}
inline void add_(int x,int l,int r,ll d){
	add[x] += d;
	sum[x] += (ll)d * (r - l + 1);
}
inline void pushdown(int x,int l,int r,int mid){
	if ( add[x] != 0 ){
		add_(x << 1,l,mid,add[x]);
		add_((x << 1) | 1,mid + 1,r,add[x]);
		add[x] = 0;
	}
}
inline void update(int x){
	sum[x] = sum[x << 1] + sum[(x << 1) | 1];
}
void modify(int x,int l,int r,int L,int R,int d){
	if ( L > R ) return;
	if ( L <= l && R >= r ){
		add_(x,l,r,d);
		return;
	}
	int mid = (l + r) >> 1;
	pushdown(x,l,r,mid);
	if ( L <= mid ) modify(x << 1,l,mid,L,R,d);
	if ( R > mid ) modify((x << 1) | 1,mid + 1,r,L,R,d);
	update(x);
}
ll query(int x,int l,int r,int L,int R){
	if ( L > R ) return 0;
	if ( L <= l && R >= r ) return sum[x];
	int mid = (l + r) >> 1; ll res = 0;
	pushdown(x,l,r,mid);
	if ( L <= mid ) res = query(x << 1,l,mid,L,R);
	if ( R > mid ) res += query((x << 1) | 1,mid + 1,r,L,R);
	return res;
}
void modify(int x,int k,int d){
	if ( tag[x] ){
		if ( k == 2 ){
			//环上的点和儿子的bfs序连续,但其他点不一定连续
			//bfs序只满足同一层的所有儿子连续的性质
			modify(1,1,n,l[pre[x]] - 1,r[pre[x]],d);
			//modify(1,1,n,dfn[pre[x]],dfn[pre[x]],d);
			modify(1,1,n,l[post[x]] - 1,r[post[x]],d);
			//modify(1,1,n,dfn[post[x]],dfn[post[x]],d);
			modify(1,1,n,l2[x],r2[x],d);
			modify(1,1,n,l[x] - 1,r[x],d);
			if ( tot == 3 );
			else if ( tot == 4 ) modify(1,1,n,dfn[pre[pre[x]]],dfn[pre[pre[x]]],d);
			else{
				modify(1,1,n,dfn[pre[pre[x]]],dfn[pre[pre[x]]],d);
				modify(1,1,n,dfn[post[post[x]]],dfn[post[post[x]]],d);
			}
		
		}
		else if ( k == 1 ){
			modify(1,1,n,dfn[pre[x]],dfn[pre[x]],d);
			modify(1,1,n,dfn[post[x]],dfn[post[x]],d);
			modify(1,1,n,l[x] - 1,r[x],d);
			//modify(1,1,n,dfn[x],dfn[x],d);
		}
		else modify(1,1,n,dfn[x],dfn[x],d);
	}	
	else{
		int p = fa[x];
		if ( k == 2 ){
			modify(1,1,n,l2[x],r2[x],d);
			modify(1,1,n,l[x],r[x],d);
			modify(1,1,n,dfn[p],dfn[p],d);
			modify(1,1,n,l[p],r[p],d);
			if ( tag[p] ){
				modify(1,1,n,dfn[pre[p]],dfn[pre[p]],d);
				modify(1,1,n,dfn[post[p]],dfn[post[p]],d);
			}
			else modify(1,1,n,dfn[fa[p]],dfn[fa[p]],d);
		}
		else if ( k == 1 ){
			modify(1,1,n,l[x],r[x],d);
			modify(1,1,n,dfn[x],dfn[x],d);
			modify(1,1,n,dfn[p],dfn[p],d);
		}
		else modify(1,1,n,dfn[x],dfn[x],d);
	}
}
ll query(int x,int k){
	ll res = 0;
	if ( tag[x] ){
		if ( k == 2 ){
			res += query(1,1,n,l2[x],r2[x]);
			res += query(1,1,n,l[x] - 1,r[x]);
				
			res += query(1,1,n,l[pre[x]] - 1,r[pre[x]]);
			res += query(1,1,n,l[post[x]] - 1,r[post[x]]);
			if ( tot == 3 );
			else if ( tot == 4 ) res += query(1,1,n,dfn[pre[pre[x]]],dfn[pre[pre[x]]]);
			else{
				res += query(1,1,n,dfn[pre[pre[x]]],dfn[pre[pre[x]]]);
				res += query(1,1,n,dfn[post[post[x]]],dfn[post[post[x]]]);
			}
		}
		else if ( k == 1 ){
			res += query(1,1,n,l[x] - 1,r[x]);
			res += query(1,1,n,dfn[pre[x]],dfn[pre[x]]);
			res += query(1,1,n,dfn[post[x]],dfn[post[x]]);
		}
		else res += query(1,1,n,dfn[x],dfn[x]);
	}
	else{
		int p = fa[x];
		if ( k == 2 ){
			res += query(1,1,n,l2[x],r2[x]);
			res += query(1,1,n,l[x],r[x]);
			res += query(1,1,n,dfn[p],dfn[p]);
			res += query(1,1,n,l[p],r[p]);

			if ( tag[p] ){
				res += query(1,1,n,dfn[pre[p]],dfn[pre[p]]);
				res += query(1,1,n,dfn[post[p]],dfn[post[p]]);
			}
			else res += query(1,1,n,dfn[fa[p]],dfn[fa[p]]);
		}
		else if ( k == 1 ){
			res += query(1,1,n,l[x],r[x]);
			res += query(1,1,n,dfn[x],dfn[x]);
			res += query(1,1,n,dfn[p],dfn[p]);
		}
		else res += query(1,1,n,dfn[x],dfn[x]);
	}
	return res;
}
int main(){
	freopen("input.txt","r",stdin);
	scanf("%d",&T);
	while ( T-- ){
		scanf("%d",&n);
		clear();
		rep(i,1,n){
			int x,y;
			scanf("%d %d",&x,&y);
			adde(x,y) , adde(y,x);
		}
		init();
	/*	for (int i = 1 ; i <= n ; i++){
			cout<<dfn[i]<<" "<<l[i]<<" "<<r[i]<<" "<<l2[i]<<" "<<r2[i]<<endl;
		}*/
		scanf("%d",&m);
		while ( m-- ){
			scanf("%s",ch);
			int x,k,d;
			if ( ch[0] == 'M' ){
				scanf("%d %d %d",&x,&k,&d);
				modify(x,k,d);
			}
			else{
				scanf("%d %d",&x,&k);
				printf("%lld\n",query(x,k));
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42484877/article/details/83274490