试题限制均为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. delphi文件名获取方法

    取文件名 ExtractFileName(FileName); 取文件扩展名: ExtractFileExt(filename); 取文件名,不带扩展名: 方法一:   Function Extrac ...

  2. English trip V1 - 7.My dream car 我梦想的车 Teacher:Lamb Key: famous for

    中华In this lesson you will learn to describe an object(目标). 课上内容(Lesson) famous for   以…著称,闻名 国家(名词)  ...

  3. Nikita and stack CodeForces - 756C (栈,线段树二分)

    大意: 给定m个栈操作push(x)或pop(), 栈空时pop()无作用, 每个操作有执行的时间$t$, 对于每个$0 \le i \le m$, 输出[1,i]的栈操作按时间顺序执行后栈顶元素. ...

  4. P4173 残缺的字符串 fft

    题意:给你两个字符串,问你第一个在第二个中出现过多少次,并输出位置,匹配时是模糊匹配*可和任意一个字符匹配 题解:fft加速字符串匹配; 假设上面的串是s,s长度为m,下面的串是p,p长度为n,先考虑 ...

  5. Leetcode 86

    /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode ...

  6. python 爬虫之为什么使用opener对象以及为什么要创建全局默认的opener对象

    基本的urlopen()函数不支持验证.cookie或其他HTTP高级功能.要支持这些功能,必须使用build_opener()函数来创建自己的自定义Opener对象. install_opener( ...

  7. 贴心的vs 备注提醒功能

  8. 生成输出 URL(16.2)

    1.在视图中生成输出 URL 几乎在每一个 MVC 框架应用程序中,你都会希望让用户能够从一个视图导航到另一个视图 —— 通常的做法是在第一个视图中生成一个指向第二个视图的链接,该链接以第二个视图的动 ...

  9. Error when clicking other button after displaying Popup window(转)

    原文地址:Error when clicking other button after displaying Popup window Hi, I'm developing a custom page ...

  10. 不能将Lnode * 类型的值分配到Lnode * 类型的实体

    typedef struct { int data; struct Lnode *next;}Lnode,*LinkList; 这个地方有点问题,因为结构体定义中出现了struct Lnode但 Ln ...