19-10-18-Night-U
话说T3:
一句话题意……见过这个嘛……
于是:$\sum \limits_{i!=j} \binom{a_i+b_i+a_j+b_j}{a_i+a_j}$
------------前言结束----------------
------------正文开始----------------
正文加载中……
T1
倍增,又是倍增。
于是找到节点$i$的祖先链上第一个比它大的点,并以他为$fa_{i,0}$
这样跑跑倍增就可以了。
(虽然我是直接跳$fa$水果的)
这里是蒟蒻竞争场+的赢家的代码,仿佛是正解。
#include<bits/stdc++.h> using namespace std; #define maxn 101000 #define inf 2000000000 int n,que,w[maxn],u,v,c; int head[maxn],js,deep[maxn],fa[maxn][25]; struct node{int ne,to;}tree[maxn*2]; void qxx(int fr,int tt) { tree[++js].ne=head[fr]; head[fr]=js; tree[js].to=tt; } int find(int ro,int c) { if(w[ro]>c) return ro; for(int j=20;j>=0;--j) if(w[fa[ro][j]]<=c) ro=fa[ro][j]; return fa[ro][0]; } void dfs(int ff,int ro) { for(int i=head[ro];i;i=tree[i].ne) { int son=tree[i].to; if(son==ff) continue; deep[son]=deep[ro]+1; int ls=find(ro,w[son]); fa[son][0]=ls; for(int j=1;j<=20;++j) fa[son][j]=fa[fa[son][j-1]][j-1]; dfs(ro,son); } } int ask(int son,int ro) { int sum=0; for(int j=20;j>=0;--j) if(deep[fa[son][j]]>=deep[ro]) { son=fa[son][j]; sum+=(1<<j); } return sum; } int main() { scanf("%d%d",&n,&que); for(int i=1;i<=n;++i) scanf("%d",&w[i]); for(int i=1;i<n;++i) { scanf("%d%d",&u,&v); qxx(u,v); qxx(v,u); } deep[1]=1; w[0]=inf; dfs(0,1); for(int o=1;o<=que;++o) { scanf("%d%d%d",&u,&v,&c); int fir=find(u,c); if(deep[fir]<deep[v]) {puts("0"); continue;} else { int ans=1; int ls=ask(fir,v); //cout<<fir<<"->"<<v<<":"<<ls<<endl; ans+=ls; printf("%d\n",ans); } } return 0; }
T2
三元环计数,虽然没A但是可以口胡一下
首先因为走最短的环所以并不能走四元环,
因为在竞赛图里,
两点之间一定有边相连,所以一定可以将四元环拆成两个三元环来走。
T3
考场上丢出一个暴力,获得20分,后来说可以把柿子化成:
注释:
蒟蒻竞技场是比谁最后一个AC的竞技场,
由超级大蒟蒻Miemeng发起,
但是他非常不要×的自己拿了很多Rank1
Miemeng真的蒻