试题限制均为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;
}

标解

用\(

最新文章

  1. IOS 类似微博,#话题#,@人,[表情] 网址 正则匹配
  2. ASP.net如何保证EF操作类线程内唯一
  3. discuz!安装遇到问题的解决方案
  4. UVA3026Period(最短循环节)
  5. BZOJ 3907: 网格
  6. html5响应式设置&lt;meta&gt;
  7. HTTP - Cookie 机制
  8. 关于全局变量和函数,在其他类中调用问题,extern关键字
  9. RandomAccessFile和memory-mapped files
  10. javascript实现倒计时程序
  11. 四个机器学习一步一步入门约束波尔兹曼机RBM
  12. 对JDK的深入理解
  13. 工具(5): 极简开发文档编写(How-to)
  14. [LeetCode] Random Pick with Blacklist 带黑名单的随机选取
  15. ubuntu默认的Python版本号修改
  16. Jmeter下载安装配置及使用(windows)
  17. xadmin后台导出时gunicorn报错ascii
  18. 格林威治时间(GTM)转北京时间
  19. 解决CentOS安装redis局域网内无法访问的问题
  20. RedLock 实现分布式锁

热门文章

  1. protected internal == internal
  2. Linux : 密码正确不能正常登陆,日志提示Could not get shadow information for user
  3. English trip -- VC(情景课)4 D
  4. 4-1 contag_tag:返回HTMLtag.
  5. Confluence 6 快捷键
  6. 关于一些逗逼函数//atoi,itoa,strtok,strupr,
  7. 开源软件架构总结之——Asterisk(DSL、组件、多线程)
  8. qt +ChartDirector 绘制图表
  9. 14 printf输出格式及栈空间分配
  10. Flask初级(五)flash在模板中使用继承,模板的模板