考试过程:

惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打。

看T2 字符串题,完了我字符串最弱了,肯定只能打暴力了,带着前两题都不会的心情,看了T3发现是期望,完了爆0了,在一看,发现是sb原题,还简单一点,赶紧把T3码了一遍过大样例,觉得很稳就交了,然后用一点时间把T1树的分给码了,然后开始磨T2,发现啥都不会开始dfs,一开始觉得只能拿30pts,后来发现没有回溯是$O(n^2)$的,打完就没剩多少时间了,然后考虑T3要不要开long long,觉得没必要就没开石乐智。然后想T1无果。

出分发现T3WA 80,然后把开了long long的代码交上去A了,我怕不是个傻子,不卡时间为什么不开long long啊QAQ。T2A了,T140,后来听说用树的方法跑所有测试点能拿60,艹。少两句话少拿40.jpg。

扯多了2333

题解:

T1 attack:

据说是什么支配树裸题,蒟蒻不会,只能照着题解打。

必经关系是一棵树,这好像就是支配树?那么1到k的必经点就是k在这棵树上的祖先,所以我们在有向图中跑个拓扑排序,就可以建出这棵树,但实际上我们并不需要真正建出这棵树,只需要维护求lca所用的fa数组和dep数组即可。另外,因为题目中说所有点都从1开始,所以一开始只要把1入队就吼了。

再说一下我的sb手残错误

求lca:

我是大设备

 #include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
const int INF=1e9+;
int first[N],nex[N<<],to[N<<],tot;
void add(int a,int b){
to[++tot]=b,nex[tot]=first[a],first[a]=tot;
}
vector<int> in[N];
int d[N],du[N],fa[N][],v[N],w[N];
int Lca(int x,int y){
if(d[x]>d[y]) swap(x,y);
for(int i=;i>=;--i) if(d[fa[y][i]]>=d[x]) y=fa[y][i];
if(x==y) return x;
for(int i=;i>=;--i) if(fa[y][i]!=fa[x][i]) y=fa[y][i],x=fa[x][i];
return fa[x][];
} int main(){
int n,m,que;
scanf("%d%d%d",&n,&m,&que);
for(int i=;i<=m;++i){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
in[y].push_back(x);
du[y]++;
}
queue<int> q;
q.push();
// d[1]=0;
/*for(int i=1;i<=n;++i){
if(!du[i]){
int lca=in[i][0];
for(int j=1;j<in[i].size();++j) lca=Lca(lca,in[i][j]);
fa[i][0]=lca;
d[i]=d[lca]+1;
for(int j=1;j<=16;++j) fa[i][j]=fa[fa[i][j-1]][j-1];
q.push(i);
v[i]=1;
}
}*/
// for(int i=1;i<=n;++i) if(!du[i]) q.push(i)/*,du[i]=INF*/;
while(q.size()){
int x=q.front();q.pop();//cout<<x<<endl;
for(int i=first[x];i;i=nex[i]){
int y=to[i];
du[y]--;
if(!du[y]){
int lca=in[y][];
for(int j=;j<in[y].size();++j) lca=Lca(lca,in[y][j]);
fa[y][]=lca;
d[y]=d[lca]+;
q.push(y);
// du[i]=INF;
for(int j=;j<=;++j) fa[y][j]=fa[fa[y][j-]][j-];
}
}
}
// for(int i=1;i<=n;++i,cout<<endl) for(int j=1;j=16;++j) cout<<fa[i][j]<<" ";
for(int i=;i<=que;++i){
int k;
scanf("%d",&k);
for(int j=;j<=k;++j) scanf("%d",&w[j]);
int lca=w[];
for(int j=;j<=k;++j) lca=Lca(lca,w[j]);
printf("%d\n",d[lca]+);
}
}
/*
4 3 2
1 2
2 3
2 4
2 3 4
2 2 4
*/

attack

T2 reverse:

只需要考虑最后一位是什么就好了,然后谁长就缩谁,直到他们两个一样长,就一起缩,博主打的是dfs,细节很多,很难调,所以代码就不提供了,所以就以soul神的代码为参考吧。

鸣谢soul

 #include<bits/stdc++.h>
#define re register
using namespace std;
int T,a[],b[]; char s[]; int len;
inline bool cmp(){
if(a[]!=b[]) return ;
for(re int i=;i<=a[];++i)
if(a[i]!=b[i]) return ;
return ;
}
signed main(){
scanf("%d",&T);
while(T--){
scanf("%s",s+);len=strlen(s+); a[]=;
for(re int i=;i<=len;++i) a[++a[]]=(s[i]-);
scanf("%s",s+);len=strlen(s+); b[]=;
for(re int i=;i<=len;++i) b[++b[]]=(s[i]-);
while(a[]&&b[]&&!cmp()){
if(a[]>b[])
while(a[]>b[]){
if(a[a[]--])
for(re int i=,lim=(a[]>>);i<=lim;++i) swap(a[i],a[a[]-i+]);
}
else if(a[]<b[])
while(b[]>a[]){
if(b[b[]--])
for(re int i=,lim=(b[]>>);i<=lim;++i) swap(b[i],b[b[]-i+]);
}
else if(a[]==b[]){
if(a[a[]--])
for(re int i=,lim=(a[]>>);i<=lim;++i) swap(a[i],a[a[]-i+]);
if(b[b[]--])
for(re int i=,lim=(b[]>>);i<=lim;++i) swap(b[i],b[b[]-i+]);
}
}
if(a[]){for(re int i=;i<=a[];++i) putchar(a[i]+); puts("");}
else puts("-1");
}
return ;
}

reverse

T3 tree:

原题,不,比原题简单,然后赛时第一个提交,成功long long见祖宗,喜提WA80。

题解是什么方法我也不知道,所以就用自己的方法说了还不是颓的以前的题解。

我们设$f[x]$表示从$x$到$fa[x]$的期望步数,$g[x]$表示从$fa[x]$到$x$的期望步数。

考虑转移$f[x]=\frac{1}{du[x]}+\sum{\frac{f[son]+1+f[x]}{du[x]}}$

挺显然的,就是他可以直接上去,也可能先下去在上去。

化简得$f[x]=du[x]+\sum{f[son]}$,一遍dfs可以求出

在来考虑g的转移$g[x]=\frac{1}{du[fa]}+\frac{1+g[x]+g[fa]}{du[fa]}+\frac{\sum{g[x]+1+f[brothers]}}{du[fa]}$

其实和f的转移也差不多就是分类讨论,可以直接下去,可以到x的兄弟节点也可以到x的父节点的父节点。

化简得$g[x]=du[fa]+g[fa]+\sum{f[bother]}$

然后树上前缀和就可以求出从根到x的期望步数了。

吐槽:

考试时知道答案一定是整数就没开double,然后,关于int,他死了最后都想到开long long了为什么不交啊,我的首杀。

 //yuanti
//xingkuizuoguo
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
#define int long long
int first[N],nex[N<<],to[N<<],tot;
void add(int a,int b){
to[++tot]=b,nex[tot]=first[a],first[a]=tot;
}
int f[N],g[N];//f[x] x->fa[x] g[x] fa[x]->x
int sumg[N],sumf[N];
int du[N];
void dfs(int x,int fa){
f[x]=du[x];
for(int i=first[x];i;i=nex[i]){
int y=to[i];
if(y==fa) continue;
dfs(y,x);
f[x]+=f[y];
}
sumf[x]=f[x];
}
void dfs1(int x,int fa){
for(int i=first[x];i;i=nex[i]){
int y=to[i];
if(y==fa) continue;
g[y]=sumf[x]-f[y]+g[x];
dfs1(y,x);
}
}
void dfs2(int x,int fa){//cout<<fa<<" "<<g[fa]<<" "<<sumg[fa]<<endl;
sumg[x]=sumg[fa]+g[x];
for(int i=first[x];i;i=nex[i]){
int y=to[i];
if(y==fa) continue;
dfs2(y,x);
}
} signed main(){
int n;
scanf("%lld",&n);
for(int i=;i<n;++i){
int x,y;
scanf("%lld%lld",&x,&y);
add(x,y);
add(y,x);
du[x]++;du[y]++;
}
dfs(,);
f[]=;
dfs1(,);
sumg[]=g[];
dfs2(,);
// for(int i=1;i<=n;++i) cout<<"f["<<i<<"]=="<<f[i]<<" ";
// cout<<endl;
// for(int i=1;i<=n;++i) cout<<"g["<<i<<"]=="<<g[i]<<" ";
// cout<<endl;
for(int i=;i<=n;++i){
printf("%lld.000\n",sumg[i]+);
}
}
/*
3
1 2
2 3
*/

tree

CSP-S 模拟测试 51 题解的更多相关文章

  1. [CSP-S模拟测试51]题解

    错失人生中第一次AK的机会…… A.attack 支配树板子题.考场上发明成功√ 首先支配树上两点路径之间的点都是必经之点,根据这个性质我们就可以yy出建树的方法.跑拓扑,在每个点(设为$x$)即将入 ...

  2. csp-s模拟测试51(b)attack,tree题解

    题面:https://www.cnblogs.com/Juve/articles/11598286.html attack: 支配树裸题? 看一下支配树是什么: 问题:我们有一个有向图(可以有环),定 ...

  3. [考试反思]0924csp-s模拟测试51:破碎

    总参赛人数:15 有点菜. 不知道是撞了什么大运没有滚出A层. 但是一回到A层就暴露出了一个大问题:码速. 不是调试速度,,就是纯粹码的速度... 边讲考试状态边说吧... 上来肝T1.一看,是个换根 ...

  4. CSP-S 模拟测试94题解

    T1 yuuustu: 可以对两边取对数,然后就转化为两个double的比较,时间复杂度$O(n)$ 然后我就用神奇0.4骗分水过 #include<bits/stdc++.h> usin ...

  5. CSP-S模拟测试 88 题解

    T1 queue: 考场写出dp柿子后觉得很斜率优化,然后因为理解错了题觉得斜率优化完全不可做,只打了暴力. 实际上他是可以乱序的,所以直接sort,正确性比较显然,贪心可证,然后就是个sb斜率优化d ...

  6. CSP-S 模拟测试92 题解

    话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊 T1 array: 根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好 ...

  7. CSP-S 模拟测试57题解

    人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...

  8. CSP-S 模拟测试 45 题解

    由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...

  9. [CSP-S模拟测试97]题解

    A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...

随机推荐

  1. Thinking In Java 4th Chap2 一切都是对象

    对基本数据类型的初始化有二: 1.String s="asdf"; 2.String s=new String("asdf"); 可能的存储区域: 寄存器(不可 ...

  2. Python_oneday

    基本程序设计 一切代码输入,请使用英文输入法   编写一个简单的程序 圆公式面积: area = radius * radius * 3.1415   在Python里面不需要定义数据的类型   控制 ...

  3. Java多线程(十一):线程组

    线程组 线程组可以批量管理线程和线程组对象. 一级关联 例子如下,建立一级关联. public class MyThread43 implements Runnable{ public void ru ...

  4. 泛型约束:接口约束、new()构造函数约束、组合约束(即多种约束合并)

    泛型 接口约束: using System; namespace ConsoleApp1 { /* * * 接口约束:where T:interfaceName * T是类型形参的名称,interfa ...

  5. virtual和override

    偶然间看到的题,借此记录. class Program { static void Main(string[] args) { D d = new D(); //第一个D是申明类,第二个D是实例类 A ...

  6. Hexo折腾记--小白修改新主题

    UPDATE 2019.5.28 不好意思我又换了个新主题ARIA啦...这回没有个人定制了 前言 如果您曾经来过我的博客,就会发现我的个人博客(https://rye-catcher.github. ...

  7. spark2.0新特性之DataSet

    1.Spark SQL,DataFrame,DataSet的错误类型检测时机 spark SQL:其类型检测与语法检测是在运行时检测的 DataFrame:在spark2.0以前的版本中,DataFr ...

  8. 14.MySQL主从复制

    1.复制的基本原理 三步骤 + 原理图 1.1 master将改变记录到二进制文件(binary log),这些记录过程叫做二进制日志事件, binary log events 1.2 slave 将 ...

  9. 16.Listener(监听器)

    /*监听器*/ java的事件监听机制(主要是对一些web元素的监听 (ServletContext(计时器),HttpSession和ServletRequest)) 1.事件监听涉及到三个组件:事 ...

  10. 一 :了解MVC

    介绍 1. ASP.NET WebForm和ASP.NET MVC是并行的关系.都是属于.NET框架下的子框架. 2. MVC项目常用模板 空模板 :   不包含MVC目录结构,需要自己添加. 基本模 ...