[bfs序 线段树] HDU5957. Query on a graph
来源:互联网 发布:nginx 反向代理 403 编辑:程序博客网 时间:2024/05/21 22:59
求出bfs序
那么一个点的儿子和孙子都是在bfs序上连续的一段
记一下这个区间,然后线段树维护一下
因为有环,那么肯定有多出来的一条边,给这条边的两个端点以及这两个端点连出去的点打个标记就好了
细节贼多
#include <cstdio>#include <iostream>#include <algorithm>#include <queue>using namespace std;typedef long long ll;const int N=100010;int n,t,q,cnt,m,G[N];struct edge{ int t,nx;}E[N<<1];inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){ char c=nc(); x=0; int f=1; for(;c>'9'||c<'0';c=nc())if(c=='-')f=-f;for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); x*=f;}inline void addedge(int x,int y){ E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt; E[++cnt].t=x; E[cnt].nx=G[y]; G[y]=cnt;}int fa[N],vis[N],sl[N],sr[N],gsl[N],gsr[N],Q[N],pos[N],d1[N],d2[N];int l,r;inline void bfs(){ vis[1]=1; Q[l=r=1]=1; pos[1]=1; while(l<=r){ int x=Q[l++]; for(int i=G[x];i;i=E[i].nx) if(!vis[E[i].t]){ Q[++r]=E[i].t; pos[E[i].t]=r; fa[E[i].t]=x; vis[E[i].t]=1; } } for(int k=r;k;k--){ int x=Q[k]; sl[x]=gsl[x]=1<<30; sr[x]=gsr[x]=0; for(int i=G[x];i;i=E[i].nx) if(fa[E[i].t]==x){ sl[x]=min(sl[x],pos[E[i].t]); sr[x]=pos[E[i].t]; gsl[x]=min(gsl[x],sl[E[i].t]); gsr[x]=max(sr[E[i].t],gsr[x]); } } for(int i=1;i<=n;i++) d1[i]=d2[i]=0; for(int k=2;k<=cnt;k++){ int x=E[k].t,y=E[k^1].t; if(fa[x]==y || fa[y]==x) continue; d1[x]=y; d1[y]=x; for(int i=G[x];i;i=E[i].nx) if(E[i].t!=y) d2[E[i].t]=y; for(int i=G[y];i;i=E[i].nx) if(E[i].t!=x) d2[E[i].t]=x; }}void PutAns(ll x){ if(x>=10) PutAns(x/10); putchar(x%10+'0');}ll tag[N<<2],tot[N<<2],size[N<<2];void Build(int g,int l,int r){ tag[g]=tot[g]=0; size[g]=r-l+1; if(l==r) return ; int mid=l+r>>1; Build(g<<1,l,mid); Build(g<<1|1,mid+1,r);}inline void add(int g,ll x){ tag[g]+=x; tot[g]+=size[g]*x;}inline void Push(int g){ if(!tag[g]) return ; add(g<<1,tag[g]); add(g<<1|1,tag[g]); tag[g]=0;}inline void Up(int g){ tot[g]=tot[g<<1]+tot[g<<1|1];}void Modify(int g,int l,int r,int L,int R,ll x){ if(l>r) return; if(l==L && r==R) return add(g,x); int mid=L+R>>1; Push(g); if(r<=mid) Modify(g<<1,l,r,L,mid,x); else if(l>mid) Modify(g<<1|1,l,r,mid+1,R,x); else Modify(g<<1,l,mid,L,mid,x),Modify(g<<1|1,mid+1,r,mid+1,R,x); Up(g);}ll Query(int g,int l,int r,int L,int R){ if(l>r) return 0; if(l==L && r==R) return tot[g]; int mid=L+R>>1; Push(g); if(r<=mid) return Query(g<<1,l,r,L,mid); else if(l>mid) return Query(g<<1|1,l,r,mid+1,R); else return Query(g<<1,l,mid,L,mid)+Query(g<<1|1,mid+1,r,mid+1,R);}int main(){ read(t); while(t--){ read(n); cnt=1; for(int i=1;i<=n;i++) G[i]=vis[i]=fa[i]=0; for(int i=1,x,y;i<=n;i++) read(x),read(y),addedge(x,y); bfs(); Build(1,1,n); read(m); for(int i=1;i<=m;i++){ char opt; while((opt=nc())!='M' && opt!='Q'); if(opt=='M'){ int x,k,d; read(x); read(k); read(d); if(k==0) Modify(1,pos[x],pos[x],1,n,d); else if(k==1){ Modify(1,pos[x],pos[x],1,n,d); Modify(1,sl[x],sr[x],1,n,d); if(fa[x]) Modify(1,pos[fa[x]],pos[fa[x]],1,n,d); if(d1[x]) Modify(1,pos[d1[x]],pos[d1[x]],1,n,d); } else{ if(fa[x]){ Modify(1,pos[fa[x]],pos[fa[x]],1,n,d); Modify(1,sl[fa[x]],sr[fa[x]],1,n,d); if(fa[fa[x]]) Modify(1,pos[fa[fa[x]]],pos[fa[fa[x]]],1,n,d); } else Modify(1,pos[x],pos[x],1,n,d); Modify(1,sl[x],sr[x],1,n,d); Modify(1,gsl[x],gsr[x],1,n,d); if(d1[x]){ int y=d1[x]; if(fa[y] && fa[x]!=fa[y] && fa[y]!=fa[fa[x]] && fa[fa[y]]!=fa[x]) Modify(1,pos[fa[y]],pos[fa[y]],1,n,d); if(fa[y]!=fa[x]) Modify(1,pos[y],pos[y],1,n,d); Modify(1,sl[y],sr[y],1,n,d); } if(d2[x] && fa[d2[x]]!=fa[x] && fa[fa[d2[x]]]!=x && fa[d2[x]]!=x) Modify(1,pos[d2[x]],pos[d2[x]],1,n,d); } } else{ ll ans=0; int x,k; read(x); read(k); if(k==0) ans=Query(1,pos[x],pos[x],1,n); else if(k==1){ ans=Query(1,pos[x],pos[x],1,n)+Query(1,sl[x],sr[x],1,n); if(fa[x]) ans+=Query(1,pos[fa[x]],pos[fa[x]],1,n); if(d1[x]) ans+=Query(1,pos[d1[x]],pos[d1[x]],1,n); } else{ if(fa[x]){ ans=Query(1,pos[fa[x]],pos[fa[x]],1,n)+Query(1,sl[fa[x]],sr[fa[x]],1,n); if(fa[fa[x]]) ans+=Query(1,pos[fa[fa[x]]],pos[fa[fa[x]]],1,n); } else ans=Query(1,pos[x],pos[x],1,n); ans+=Query(1,sl[x],sr[x],1,n); ans+=Query(1,gsl[x],gsr[x],1,n); if(d1[x]){ int y=d1[x]; if(fa[y] && fa[y]!=fa[x] && fa[y]!=fa[fa[x]] && fa[fa[y]]!=fa[x]) ans+=Query(1,pos[fa[y]],pos[fa[y]],1,n); if(fa[y]!=fa[x]) ans+=Query(1,pos[y],pos[y],1,n); ans+=Query(1,sl[y],sr[y],1,n); } if(d2[x] && fa[d2[x]]!=fa[x] && fa[fa[d2[x]]]!=x && fa[d2[x]]!=x) ans+=Query(1,pos[d2[x]],pos[d2[x]],1,n); } if(ans<0) putchar('-'),ans=-ans; PutAns(ans); putchar('\n'); } //for(int i=1;i<=n;i++) printf("%lld ",Query(1,pos[i],pos[i],1,n)); putchar('\n'); } } return 0;}
阅读全文
0 0
- [bfs序 线段树] HDU5957. Query on a graph
- Query on a graph HDU5957 沈阳ICPC重现赛
- 【HDU】5957 Query on a graph【分类讨论+bfs序线段树】
- HDU-5957 Query on a graph(线段树+树剖)
- Query on a string【线段树】
- 计蒜客 Query on a string 线段树
- Query on a string 线段树
- ZOJ 1103 Hike on a Graph(BFS)
- hdu 1252 Hike on a Graph(bfs)
- hdu1252 Hike on a Graph ----BFS
- SPOJ - QTREE 375 Query on a tree 树链剖分+线段树
- 【HDU】3804 Query on a tree dfs+线段树
- 【线段树】CSU 1414 Query on a Tree
- SPOJ 375 Query on a tree (树链剖分+线段树)
- SPOJ Query on a tree (树链剖分 + 线段树)
- 树链剖分+线段树 spoj375 Query on a tree
- SPOJ QTREE Query on a tree [树链剖分+线段树]
- spoj qtree Query on a tree 【线段树+树链剖分】
- dubbo核心技术原理:RPC调用协议
- 安装cuda
- 5、如何自己写SQL语句
- dup2 复制文件描述符
- Spark Core
- [bfs序 线段树] HDU5957. Query on a graph
- 编写一个应用程序,用户分别从两个文本框输入学术的姓名和分数,程序按成绩排序将这些学生的姓名和分数显示在一个文本区中
- Microsoft OneNote
- ARP原理、利用、防御(链路层)
- C 语言 define 变参__VA_ARGS__使用
- ELK第五篇:mapping的创建和中文模糊查询
- Java中的String为什么是不可变的?
- 在自己的数据集上微调Light CNN
- RecyclerView的基本用法与四种数据展示(listview,griderview,单行,多行)