试题限制均为128MB,1Sec

总分150.

试题一

A题

问题描述:

小A得到了一棵美丽的有根树。这棵树由n个节点以及n - 1条有向边构成,每条边都从父亲节点指向儿子节点,保证除了根节点以外的每个节点都有一个唯一的父亲。树上的节点从1到n标号。该树的一棵子树的定义为某个节点以及从该节点出发能够达到的所有节点的集合,显然这棵树共有n棵子树。小A认为一棵有根树是美丽的当且仅当这棵树内节点的标号构成了一个连续的整数区间。现在小A想知道这棵树上共有多少棵美丽的子树。

输入:

第一行有一个整数n,表示树的节点数。

接下来n–1行,每行两个整数u,v,表示存在一条从u到v的有向边。

输入保证该图是一棵有根树。

输出:

输出一个整数占一行,表示对应的答案。

样例输入:

4

2 3

2 1

2 4

样例输出:

3

数据范围:

对于20%的数据,\(1 ≤ n ≤ 1000\)。

对于100%的数据,\(1 ≤ n ≤ 100000\)。

分析

考场爆零做法

用后序遍历dfs,将子树中区间统计在子树根中,排序判断,是合法区间则上传区间两端点,不是合法区间则上传-1。

明显的bug,有可能子树不合法但当前根统计后交错一下就合法了。

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x){
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return x=data*w;
}
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x7fffffff; const int MAXN=1e5+7;
int n;
struct Edge
{
int nx,to;
}E[MAXN];
int head[MAXN],ecnt;
bool noroot[MAXN]; void addedge(int x,int y)
{
E[++ecnt].to=y;
E[ecnt].nx=head[x],head[x]=ecnt;
} int ans; pii dfs(int x)
{
vector<pii>a;
for(int i=head[x];i;i=E[i].nx)
a.push_back(dfs(E[i].to));
a.push_back(pii(x,x));
sort(a.begin(),a.end());
bool valid=1;
for(int i=0;i<a.size();++i)
{
if(a[i].first==-1)
{
valid=0;
break;
}
if(i&&a[i].first!=a[i-1].second+1)
{
valid=0;
break;
}
}
if(valid)
{
++ans;
return pii(a[0].first,a[a.size()-1].second);
}
else
return pii(-1,0);
} int main()
{
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
read(n);
for(int i=1;i<n;++i)
{
int x,y;
read(x);read(y);
addedge(x,y);
noroot[y]=1;
}
int r=0;
for(int i=1;i<=n;++i)
if(!noroot[i])
{
r=i;
break;
}
dfs(r);
printf("%d\n",ans);
// fclose(stdin);
// fclose(stdout);
return 0;
}

标解

简单题,一遍dfs求出每棵子树中最小顶点编号,最大顶点编号以及子树大小即可判断该子树是否满足要求。

这种做法成立的条件是节点编号两两不同。

哈哈,T1爆零导致rank很难看。

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x){
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return x=data*w;
}
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x7fffffff; const int MAXN=2e5+7;
int n;
struct Edge
{
int nx,to;
}E[MAXN];
int head[MAXN],ecnt;
bool noroot[MAXN]; void addedge(int x,int y)
{
E[++ecnt].to=y;
E[ecnt].nx=head[x],head[x]=ecnt;
} int ans;
int sz[MAXN],maxv[MAXN],minv[MAXN]; void dfs(int x)
{
sz[x]=1;
minv[x]=maxv[x]=x;
for(int i=head[x];i;i=E[i].nx)
{
int y=E[i].to;
dfs(y);
sz[x]+=sz[y];
minv[x]=min(minv[x],minv[y]);
maxv[x]=max(maxv[x],maxv[y]);
}
if(sz[x]==(maxv[x]-minv[x]+1))
++ans;
} int main()
{
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
read(n);
for(int i=1;i<n;++i)
{
int x,y;
read(x);read(y);
addedge(x,y);
noroot[y]=1;
}
int r=0;
for(int i=1;i<=n;++i)
if(!noroot[i])
{
r=i;
break;
}
dfs(r);
printf("%d\n",ans);
// fclose(stdin);
// fclose(stdout);
return 0;
}

试题二

B题

问题描述:

对于一个排列,考虑相邻的两个元素,如果后面一个比前面一个大,表示这个位置是上升的,用I表示,反之这个位置是下降的,用D表示。如排列3,1,2,7,4,6,5可以表示为DIIDID。

现在给出一个长度为n-1的排列表示,问有多少种1到n的排列满足这种表示。

输入:

一个字符串S,S由I,D,?组成。?表示这个位置既可以为I,又可以为D。

输出:

有多少种排列满足上述字符串。输出排列数模1000000007。

样例输入:

?D

样例输出:

3

数据范围:

对于20%的数据,\(S长度≤ 10\);

对于100%的数据,\(S长度 ≤ 1000\)。

分析

考场做法

用\(f(i,j)\)表示前\(i\)个数满足前\(i-1\)个条件,最后一个为\(j\)的排列数个数。

拓展一下,j表示的其实是排名。

那么已经很好处理了,j确定后前i-1个数是什么就确定了,只需要前i-1个数最后一个满足条件。

  1. i-1为?,那么\(f(i,j)=\sum_{k=1}^{i-1}f(i-1,k)\)
  2. i-1为I,那么\(f(i,j)=\sum_{k=1}^{j-1}f(i-1,k)\)
  3. i-1为D,那么\(f(i,j)=\sum_{k=j}^{i-1}f(i-1,k)\)

    第三种情况为什么k从j开始呢?因为第i-1个数要比i大,而在前i-1个数中j不存在,所以j+1以后向左平移了一位。

    然后我第二维维护的树状数组,其实前缀和就行了。

    时间复杂度\(O(N^2\log N)\)
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x){
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff; const int MAXN=1e3+7,mod=1000000007;
int n;
char s[MAXN];
int f[MAXN][MAXN]; inline int lowbit(int x)
{
return x&-x;
} inline void add(int id,int p,int v)
{
while(p<=n)
{
f[id][p]+=v;
if(f[id][p]>=mod)
f[id][p]-=mod;
p+=lowbit(p);
}
} inline int query(int id,int p)
{
int res=0;
while(p)
{
res+=f[id][p];
if(res>=mod)
res-=mod;
p-=lowbit(p);
}
return res;
} int main()
{
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
scanf("%s",s+1);
n=strlen(s+1)+1;
s[0]='?';
add(0,1,1);
// cerr<<"init end"<<endl;
for(int i=1;i<=n;++i)
for(int j=1;j<=i;++j)
{
// cerr<<"procesxing "<<i<<' '<<j<<endl;
if(s[i-1]=='?')
{
add(i,j,query(i-1,n));
}
else if(s[i-1]=='D')
{
add(i,j,(query(i-1,n)+mod-query(i-1,j-1))%mod);
}
else if(s[i-1]=='I')
{
add(i,j,query(i-1,j-1));
}
}
/* for(int i=1;i<=n;++i)
for(int j=1;j<=i;++j)
{
cerr<<i<<' '<<j<<" f="<<query(i,j)-query(i,j-1)<<endl;
}*/
printf("%d\n",query(n,n));
// fclose(stdin);
// fclose(stdout);
return 0;
}

标解

用\(

test20180829的更多相关文章

随机推荐

  1. Solaris 11, gcc 的安装

    注意点在于, 头文件在另外一个包system/header里,需要另外安装 pkg pkg install system/header

  2. JPA、SpringData JPA 、Hibernate和Mybatis 的区别和联系

    一.JPA 概述 1. Java Persistence API(Java 持久层 API):用于对象持久化的 API 2. 作用:使得应用程序以统一的方式访问持久层 3. 前言中提到了 Hibern ...

  3. 如何配置Smarty模板

    <?php //首先包含Smarty类文件 include_once('Smarty/Smarty.class.php'); //实例化Smarty类文件 $smarty=new Smarty( ...

  4. [Java学习] Java多态和动态绑定

    在Java中,父类的变量可以引用父类的实例,也可以引用子类的实例. 请读者先看一段代码: 1. public class Demo { 2. public static void main(Strin ...

  5. Python递归遍历《指定目录》下的所有《文件》

    https://www.cnblogs.com/dreamer-fish/p/3820625.html

  6. mac 地址

  7. thinkphp3.2分页

    在ThinkPHP 3.1及之前,分页功能可能是放在/Lib/Org/Util中的,到了ThinkPHP 3.2后,分页功能已经整合到了Library/Think中了.而且ThinkPHP 3.2已经 ...

  8. Unity3D中的函数方法和解释

    一.刷新函数 Update 当MonoBehaviour启用时,其Update在每一帧被调用. LateUpdate 当Behaviour启用时,其LateUpdate在每一帧被调用. FixedUp ...

  9. 一、Object类

    1.Object类是所有类的父类 声明一个类的时候,实际上已经默认继承了Object类 package property; public class Hero extends Object{ Stri ...

  10. stimulsoft report工具—— 简单的多表连接打印报表例子

    一.用报表工具打印多个表格信息(包括学生表.教师表.班级表) 1.准备打印的数据(用sqlserver) 1)班级表