【队内胡策 10.30】 T2
2017-10-31 09:38
309 查看
求一个被memset卡时的人的心理阴影面积
嗯。。多叉树。。考试的时候想成二叉树了
两个人肯定尽量去堵对方的路
所以他们一定会在一个点相遇
如果这个点还有其他分枝,按最优原则分配给两个人:
如果两个人走过的总边数为奇数,那么相遇后,下一个选择的人是Yjq,反之为Hja。每个人选择当前可以选择的分枝中子树权值最大的一个。所以预处理以每个点为根的子树的大小
这个题最麻烦的是分类求相遇点。。
总的思路:
求lca得到经过的边数
找相遇点以及到达相遇点上一步两个人所处的点
分配答案
分配答案的函数里我加了一个memset。。然后TLE了4个点。。。其实每次都修改,sort的时候只sort当前区间,是不用memset的。。。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=100000+10; int n,m,cnt,ans,Index; int fist[maxn],nxt[maxn<<1],fa[maxn][22],deep[maxn],rank[maxn]; int zi[maxn]; struct hh { int f,t,v; }e[maxn<<1]; int dfs(int f,int t,int v) { deep[t]=deep[f]+1; fa[t][0]=f; for(int i=fist[t];i!=-1;i=nxt[i]) if(f!=e[i].t) zi[t]+=dfs(t,e[i].t,e[i].v)+e[i].v; return zi[t]; } void done() { for(int i=1;i<=log2(n);++i) for(int j=1;j<=n;++j) fa[j][i]=fa[fa[j][i-1]][i-1]; } int make_lca(int x,int y) { if(deep[x]<deep[y]) swap(x,y); for(int i=log2(n);i>=0;--i) if(deep[fa[x][i]]>=deep[y]) x=fa[x][i]; if(x==y) return x; for(int i=log2(n);i>=0;--i) if(fa[x][i]!=fa[y][i]) { x=fa[x][i]; y=fa[y][i]; } return fa[x][0]; } void build(int f,int t,int v) { e[++cnt]=(hh){f,t,v}; nxt[cnt]=fist[f]; fist[f]=cnt; } int get_fa(int x,int j) { for(int i=log2(n);i>=0;--i) if(deep[fa[x][i]]>=j) x=fa[x][i]; return x; } bool cmp(int x,int y) { return x>y; } void ask_ans(int mid,int x,int y,int lca,int first) { int cnt1=0; //memset(rank,0,sizeof(rank)); if(fa[mid][0]==x) ans+=zi[1]-zi[mid]; for(int i=fist[mid];i!=-1;i=nxt[i]) { int t=e[i].t; if(t==x||t==y) { if(t==x&&t!=fa[mid][0]) ans+=zi[t]+e[i].v; continue; } if(t==fa[mid][0]) rank[++cnt1]=zi[1]-zi[lca]; else rank[++cnt1]=zi[t]+e[i].v; } sort(rank+1,rank+cnt1+1,cmp); int i=2; if(first) i=1; for(;i<=cnt1;i+=2) ans+=rank[i]; } int main() { memset(fist,-1,sizeof(fist)); scanf("%d%d",&n,&m); for(int i=1;i<n;++i) { int a,b,c; scanf("%d%d%d",&a,&b,&c); build(a,b,c); build(b,a,c); } dfs(0,1,0); done(); for(int i=1;i<=m;++i) { ans=0; int a,b; scanf("%d%d",&a,&b); int lca=make_lca(a,b); int mid,ka,kb,first=0,where; int l=deep[a]+deep[b]-2*deep[lca]; mid=(l+1)>>1; if(l%2==0) first=1; i 4000 f(l==1) where=b; else if(deep[a]>deep[b]) where=get_fa(a,deep[a]-mid); else where=get_fa(b,deep[b]-(l-mid)); if(lca!=where) { if(deep[a]-deep[lca]<mid) ka=fa[where][0]; else ka=get_fa(a,deep[a]-mid+1); if(deep[b]-deep[lca]<l-mid) kb=fa[where][0]; else kb=get_fa(b,deep[b]-(l-mid)+1); } else { ka=get_fa(a,deep[lca]+1); kb=get_fa(b,deep[lca]+1); } if(a==where) ka=0; if(b==where) kb=0; if(a==b) ka=kb=0; ask_ans(where,ka,kb,lca,first); printf("%d\n",ans); } return 0; }
相关文章推荐
- 【队内胡策 10.24 T2】术式
- 【队内胡策 10.30】T1
- 【队内胡策 11.1】 T1 T2
- 【队内胡策】2017.10.20
- 【队内胡策】令咒
- 【队内胡策 10.26 】T1
- 【队内胡策】2017.11.2
- 【队内胡策】ま ほう しょう じょ (马猴烧酒)DQS(树链剖分&&倍增LCA)
- 【队内胡策】题解
- 【队内胡策】2017.10.24
- 【队内胡策】2017.10.10
- 【队内胡策】洛圣都
- 【队内胡策】2017.10.12
- < 胡策day> 10.26 T2 人、镜子与墙
- 【胡策 9.16】Loi 队内胡策 Day1
- NOIP模拟(10.30)T2 Game
- 【队内胡策】2017.10.22
- <胡策day> 10.30 T1 小学数学
- 【队内胡策】2017.11.3
- 【队内胡策】2017.10.16