ONTAK
来源:互联网 发布:js防水涂料与水泥结合 编辑:程序博客网 时间:2024/06/05 19:58
ONTAK - 2010 - aut
给一棵
恰经过一条额外的边
不经过树上
对于一个询问
dfs离线处理询问就行了。
#include<bits/stdc++.h>using namespace std;const int N=1e5+7;vector<int> adj[N],ext[N];struct Query{ int v,id;};vector<Query> q[N];int n,Ans[N*5],sz[N],d[N],id[N],gg;namespace LCA{ int ord[N<<1],d[N<<1],fir[N],dp[N<<1][20],mm[N<<1],m=0; void dfs_lca(int u,int p,int deep) { ord[++m]=u; d[m]=deep; fir[u]=m; for(int i=0;i<adj[u].size();++i) { int v=adj[u][i]; if(v==p) continue; dfs_lca(v,u,deep+1); ord[++m]=u; d[m]=deep; } } void init_RMQ() { mm[0] = -1; for(int i=1;i<=m;++i) { mm[i]= ((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; dp[i][0]=i; } for(int j=1;j<=mm[m];++j) for(int i=1;i+(1<<j)-1<=m;++i) { int x=dp[i][j-1],y=dp[i+(1<<(j-1))][j-1]; dp[i][j]=d[x]<d[y]?x:y; } } int lca(int u,int v) { u=fir[u],v=fir[v]; if(u>v) swap(u,v); int k=mm[v-u+1]; int x=dp[u][k],y=dp[v-(1<<k)+1][k]; return d[x]<d[y]?ord[x]:ord[y]; } void init(int u) { m=0; dfs_lca(u,0,0); init_RMQ(); }}namespace SegmentTree{ int sum[N*9],s[N*9],top=0,tot=0,ls[N*9],rs[N*9]; int newnode() { int id; if(top) id=s[--top]; else id=++tot; sum[id]=ls[id]=rs[id]=0; return id; } void delnode(int x) { s[top++]=x; } void build(int &rt,int l,int r,int p) { rt=newnode(); sum[rt]=1; if(l==r) return ; int mid=(l+r)>>1; if(p<=mid) build(ls[rt],l,mid,p); else build(rs[rt],mid+1,r,p); } int Merge(int rt1,int rt2) { if(rt1==0||rt2==0) return rt1^rt2; ls[rt1]=Merge(ls[rt1],ls[rt2]); rs[rt1]=Merge(rs[rt1],rs[rt2]); sum[rt1]=sum[rt1]+sum[rt2]; delnode(rt2); return rt1; } int query(int rt,int l,int r,int ql,int qr) { if(!rt) return 0; if(ql<=l&&qr>=r) return sum[rt]; int mid=(l+r)>>1; int res=0; if(ql<=mid) res+=query(ls[rt],l,mid,ql,qr); if(qr>mid) res+=query(rs[rt],mid+1,r,ql,qr); return res; } int dfs(int u,int p) { int rt=newnode(); for(int i=0;i<adj[u].size();++i) { int v=adj[u][i]; if(v==p) continue; Merge(rt,dfs(v,u)); } for(int i=0;i<ext[u].size();++i) { int root=newnode(); build(root,1,n,id[ext[u][i]]); Merge(rt,root); } for(int i=0;i<q[u].size();++i) { int v=q[u][i].v; if(LCA::lca(u,v)==v) { int son; for(int i=0;i<adj[v].size();++i) if(LCA::lca(son=adj[v][i],u)==son&&d[son]>d[v]) break; Ans[q[u][i].id]=query(rt,1,n,1,n)-query(rt,1,n,id[son],id[son]+sz[son]-1); } else Ans[q[u][i].id]=query(rt,1,n,id[v],id[v]+sz[v]-1); } return rt; }}void dfs(int u,int p,int deep){ d[u]=deep; sz[u]=1; id[u]=++gg; for(int i=0;i<adj[u].size();++i) { int v=adj[u][i]; if(v==p) continue; dfs(v,u,deep+1); sz[u]+=sz[v]; }}int main(){ scanf("%d",&n); for(int i=1; i<n; ++i) { int u,v; scanf("%d%d",&u,&v); adj[u].push_back(v); adj[v].push_back(u); } dfs(1,0,0); LCA::init(1); int m; scanf("%d",&m); for(int i=0;i<m;++i) { int u,v; scanf("%d%d",&u,&v); ext[u].push_back(v); ext[v].push_back(u); } scanf("%d",&m); for(int i=0;i<m;++i) { int u,v; scanf("%d%d",&u,&v); if(d[u]>d[v]) q[u].push_back({v,i}); else q[v].push_back({u,i}); } SegmentTree::dfs(1,0); for(int i=0;i<m;++i) printf("%d\n",Ans[i]+1); return 0;}
阅读全文
0 0
- ONTAK
- BZOJ 3544 ONTAK 2010 Creative Accounting 贪心+平衡树
- java的poi技术读取Excel
- 常见python面试题 -- 手写代码系列
- 最短路模板
- linux系统中的grub修复
- Java中_多维数组和对象
- ONTAK
- Leetcode 129. Sum Root to Leaf Numbers
- Spring+SpringMVC+mybatis框架环境搭建总结
- C/C++ 上机考试积累之《斐波那契数列》
- 设置蓝牙名称,动态修改名称
- 解决vue中无法动态修改jqgrid组件 url地址
- 输入挂
- 支付宝余额关闭半实名技术提现方法
- PageRank计算方法及java实现