NOI2013 树的计数
85%做法:
动态规划。
首先重编号,BFS序变成1...n,然后DFS序相应重编号。
记pos[i]为i号点在DFS中的位置,即pos[d[i]]=i。
记F[l][r]表示BFS序中l...r号点相同高度时的高度和,G[l][r]表示BFS序中l...r号点相同高度的个数。
我们要寻找合法的k,使得[r+1][k]作为下一层,然后转移:
F[r+1][k]+=F[l][r]+G[l][r]
G[r+1][k]+=G[l][r]
我们要找到合法的k,k要满足以下条件:
(1)[l,r]在DFS序中的下一个一定在[1,k]中。
分析:
假设A∈[l,r],那么A在DFS序中的下一个B只有下面3种情况:
这3种情况中,B的高度最多比A多1。
[k+1,N]的点应该在[r+1,k]那一层下面,如果[l,r]在DFS序中的下一个在[k+1,N]中,就会在[r+1,k]那一层乱入一个[k+1,N]的点,这样是违法的。
所以这个条件限制了[k+1,N]进入[r+1,k]那一层。
(2)r+1在DFS序中的上一个在[l,r]中。
如下面这种情况:
如果r+1在DFS序中的上一个不在[l,r]那么,r+1就不能另开一层了。
(3)[r+1,k]在DFS序中的位置是递增的。
是为了防止这种情况发生:
时间复杂度O(N^3),然而实际上满足条件的k并不多,可以过85%的数据。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b) for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline void clear(vector<int> *A,int a,int b){int i,j;A->clear();re(i,,a)re(j,,b)A[i].push_back();} inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=; int N;
int d[maxN+],b[maxN+];
int bak[maxN+],pos[maxN+];
DB F[maxN+][maxN+],G[maxN+][maxN+];
DB sumF,sumG,ans; int main()
{
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
int i,j,k;
N=gint();
re(i,,N)d[i]=gint();
re(i,,N)b[i]=gint();
re(i,,N)bak[b[i]]=i;
re(i,,N)d[i]=bak[d[i]],b[i]=bak[b[i]];
re(i,,N)pos[d[i]]=i;
F[][]=1.0,G[][]=1.0;
re(i,,N)re(j,i,N)
{
if(G[i][j]==0.0)continue;
int t=;
re(k,i,j)upmax(t,d[pos[k]+]);
for(k=j+;k<=N;k++)
{
if(k<t)continue;
if(!(i<=d[pos[j+]-] && d[pos[j+]-]<=j))break;
if(k->=j+ && pos[k]<pos[k-])break;
F[j+][k]+=F[i][j]+G[i][j];
G[j+][k]+=G[i][j];
}
}
sumF=sumG=0.0;
re(i,,N)sumF+=F[i][N],sumG+=G[i][N];
ans=(sgn(sumG)==)?0.0:sumF/sumG;
PF("%0.3lf\n",ans);
}
100%做法:
动态规划。
首先重编号,BFS序变成1...n,然后DFS序相应重编号。
记pos[i]为i号点在DFS中的位置,即pos[d[i]]=i。
记h[i]为第i号点的期望高度。
容易知道h[1]为1,h[2]为2
我们按照BFS序从小到大枚举1到N,我们知道i号点和i-1号点高度相差0或1,且只能出现在下面蓝色框(i-1号点右边的兄弟),红色框(i-1号点左边兄弟的儿子,此时蓝色框为空)和绿色框中(i-1号点的儿子,此时蓝色框和红色框为空)。
1.pos[i-1]>pos[i]
i号点一定在红色框中,所以h[i]=h[i-1]+1
2.pos[i-1]<pos[i]
2.1 pos[i-1]+1!=pos[i]
i号点一定在蓝色框中。
如果i号点在绿色框中,那么i一定是i-1的第一个儿子,这样的话pos[i-1]+1=pos[i],矛盾,所以i号点一定在蓝色框中。
所以h[i]=h[i-1]
2.2 pos[i-1]+1=pos[i]
考虑绿色框,我们想要i号点在绿色框中就必须保证蓝色框和红色框为空。怎么保证呢?就是[1..i-1]号点在DFS序中的下一个都在[1..i]中。
2.2.1 [1..i-1]号点在DFS序中的下一个都在[1..i]中。
这时候i号点既可以在绿色框中也也可以在蓝色框中,所以h[i]=h[i-1]或h[i]=h[i-1]+1
因为这两种情况等概率,所以h[i]=h[i-1]+0.5
2.2.2 [1..i-1]号点在DFS序中的下一个并不都在[1..i]中。
这时候i号点只能在蓝色框,所以h[i]=h[i-1]
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b) for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline void clear(vector<int> *A,int a,int b){int i,j;A->clear();re(i,,a)re(j,,b)A[i].push_back();} inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=; int N;
int d[maxN+],b[maxN+];
int bak[maxN+],pos[maxN+];
DB h[maxN+]; int main()
{
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
int i;
N=gint();
re(i,,N)d[i]=gint();
re(i,,N)b[i]=gint();
re(i,,N)bak[b[i]]=i;
re(i,,N)d[i]=bak[d[i]],b[i]=bak[b[i]];
re(i,,N)pos[d[i]]=i;
int t=;
h[]=1.0;
upmax(t,d[pos[]+]);
h[]=2.0;
upmax(t,d[pos[]+]);
re(i,,N)
{
if(pos[i-]>pos[i])
h[i]=h[i-]+1.0;
else
if(pos[i-]+!=pos[i])
h[i]=h[i-];
else
if(t<=i)
h[i]=h[i-]+0.5;
else
h[i]=h[i-];
upmax(t,d[pos[i]+]);
}
PF("%0.3lf\n",h[N]);
return ;
}
NOI2013 树的计数的更多相关文章
- [UOJ#122][NOI2013]树的计数
[UOJ#122][NOI2013]树的计数 试题描述 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的 DFS 序以及 BFS 序.两棵不同的树的 DFS 序 ...
- 3244: [Noi2013]树的计数 - BZOJ
Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...
- bzoj 3244: [Noi2013]树的计数
Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...
- 【BZOJ3244】【UOJ#122】【NOI2013]树的计数
NOI都是酱的题怎么玩啊,哇.jpg 原题: 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的 ...
- BZOJ3244 NOI2013树的计数(概率期望)
容易发现的一点是如果确定了每一层有哪些点,树的形态就确定了.问题变为划分bfs序. 考虑怎样划分是合法的.同一层的点在bfs序中出现顺序与dfs序中相同.对于dfs序中相邻两点依次设为x和y,y至多在 ...
- 【uoj122】 NOI2013—树的计数
http://uoj.ac/problem/122 (题目链接) 题意 给出一棵树的dfs序和bfs序,保证一定可以构成一棵树.问构成的树的期望深度. Solution 这是一个悲伤的故事,我YY的东 ...
- [BZOJ3244][NOI2013]树的计数
这题大家为什么都写O(NlogN)的算法呢?…… 让本蒟蒻来写一个O(N)的吧…… 首先还是对BFS序和DFS序重编号,记标好的DFS序为d[1..n].令pos[x]为x在d[]中出现的位置,即po ...
- [bzoj3244][noi2013]树的计数 题解
UPD: 那位神牛的题解更新了,在这里. ------------------------------------------------------------------------------- ...
- BZOJ3244/UOJ122 [Noi2013]树的计数
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- luogu P1232 [NOI2013]树的计数
传送门 这题妙蛙 首先考虑构造出一个合法的树.先重新编号,把bfs序整成\(1,2,3...n\),然后bfs序就是按照从上到下从左往右的遍历顺序,所以可以考虑对bfs序分层,可以知道分层方式只会对应 ...
随机推荐
- 高性能Java解析器实现过程详解
如果你没有指定数据或语言标准的或开源的Java解析器, 可能经常要用Java实现你自己的数据或语言解析器.或者,可能有很多解析器可选,但是要么太慢,要么太耗内存,或者没有你需要的特定功能.或者开源解析 ...
- Scala-的元组和映射
package com.mengyao.scala.function /** * Scala 映射 * Scala中的Key,Value集合被称为映射,映射中的每一个key,value称为对偶 * ...
- httpclient post请求实例(自己写的)
package com.gop.gplus.trade.common.utils; import org.apache.commons.httpclient.HttpClient;import org ...
- 使用 AtomicInteger 进行计数(java多线程优化)
通常,在我们实现多线程使用的计数器或随机数生成器时,会使用锁来保护共享变量.这样做的弊端是如果锁竞争的太厉害,会损害吞吐量,因为竞争的同步非常昂贵. volatile 变量虽然可以使用比同步更低的成本 ...
- Spring + mybatis整合方案总结 结合实例应用
Spring + mybatis整合实例应用 项目结构图 (Spring3.0.2 +mybatis3.0.4) 方案一: 通过配置文件整合Spring和mybatis 应用数据库 -- --数据库 ...
- mysql存储过程、函数和触发器的创建 [转]
http://blog.itpub.net/559237/viewspace-438942/ 今天花了半天时间来研究mysql的存储过程函数和触发器的创建,觉得和oracle的大同小异,只是语法上更艰 ...
- Android Fragment 详解(一)
Android从3.0开始引入fragment,主要是为了支持更动态更灵活的界面设计,比如在平板上的应用.平板机上拥有比手机更大的屏幕空间来组合和交互界面组件们.Fragment使你在做那样的设计时, ...
- [Python爬虫笔记][随意找个博客入门(一)]
[Python爬虫笔记][随意找个博客入门(一)] 标签(空格分隔): Python 爬虫 2016年暑假 来源博客:挣脱不足与蒙昧 1.简单的爬取特定url的html代码 import urllib ...
- Centos 下mysql安装配置
一.编译安装MySQL前的准备工作 安装编译源码所需的工具和库 yum install gcc gcc-c++ ncurses-devel perl 安装cmake,从http://www.cmake ...
- Kendo Web UI Grid添加一个html控件如(checkbox,button)
在Kendo Web UI Grid增加一个控件如效果图: <div id="grid1"></div><script> $("#gr ...