hdu5957 ICPC-2016 瀋陽 I bfs序+線段樹+分類討論
阿新 • • 發佈:2018-12-16
思路: 用線段樹維護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)); } } } }