NOIP2016提高组模拟赛
——By wangyurzee7
中文题目名称 |
迷妹 |
膜拜 |
换数游戏 |
英文题目与子目录名 |
fans |
mod |
game |
可执行文件名 |
fans |
mod |
game |
输入文件名 |
fans.in |
mod.in |
game.in |
输出文件名 |
fans.out |
mod.out |
game.out |
每个测试点时限 |
1秒 |
1秒 |
1秒 |
测试点数目 |
20 |
16 |
16 |
每个测试点分值 |
10 |
6.25 |
6.25 |
题目类型 |
传统 |
传统 |
传统 |
运行内存上限 |
128M |
128M |
256M |
注意:评测时不打开任何优化开关
测试数据:
链接: http://pan.baidu.com/s/1eRDK43w 密码: 6sbj
迷妹
(fans.cpp/c/pas)
【问题描述】
小钟、小皓和小曦都是著名偶像派OI选手,他们都有很多迷妹。
现在,有n个妹子排成了一行,从左到右编号为1到n。这些妹子中,任意一个都是其中一个人的迷妹。
现在,蒟蒻wyz有Q个问题,第i个问题为:编号在l[i]到r[i]范围内的妹子中,分别有几个小钟的迷妹、小皓的迷妹、和小曦的迷妹。
【输入格式】
输入到fans.in
第一行2个正整数n,Q。
第2行到第n+1行每行一个正整数a[i],描述了第i个妹子是谁的迷妹。a[i]=1表示小钟的迷妹,a[i]=2表示小皓的迷妹,a[i]=3表示小曦的迷妹。
第n+2行到第n+Q+1行,每行2个整数,表示第i个问题。
【输出格式】
输出到fans.out
共Q行,每行3个用空格分开的整数,分别表示对于第i个问题,有多少小钟、小皓、小曦的迷妹。
【输入输出样例】
fans.in |
fans.out |
6 3 2 1 1 3 2 1 1 6 3 3 2 4 |
3 2 1 1 0 0 2 0 1 |
【数据范围】
对于10%的数据,保证1<=n<=10,Q<=10,
对于25%的数据,保证1<=n<=100,Q<=100,
对于45%的数据,保证1<=n<=1000,Q<=1000,
对于100%的数据,保证1<=n<=100,000,Q<=100,000。
保证1<=a[i]<=3,1<=l[i]<=r[i]<=n。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,q,x,le,ri; int a[100010],b[100010],c[100010]; int main() { freopen("fans.in","r",stdin); freopen("fans.out","w",stdout); scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) { scanf("%d",&x); switch(x) { case 1:{a[i]=a[i-1]+1;b[i]=b[i-1];c[i]=c[i-1];break;} case 2:{b[i]=b[i-1]+1;c[i]=c[i-1];a[i]=a[i-1];break;} case 3:{c[i]=c[i-1]+1;a[i]=a[i-1];b[i]=b[i-1];break;} } } for(int i=1;i<=q;i++) { scanf("%d%d",&le,&ri); printf("%d %d %d\n",a[ri]-a[le-1],b[ri]-b[le-1],c[ri]-c[le-1]); } fclose(stdin);fclose(stdout); return 0; }
膜拜
(mod.cpp/c/pas)
【问题描述】
有一个n个点m条边的有向图,wyz可以从1号点出发在图上走,并且最终需要回到1号点。每个点都有一个神犇(包括1号点),每次经过一个没到过的点,wyz都会膜拜那位神犇。wyz希望膜拜尽可能多的神犇。
由于wyz膜拜神犇的欲望非常强烈,所以他可以有一次机会逆着一条有向边的方向走。(需要注意的是,这条边的方向不会改变)
你现在想知道,wyz最多能膜拜多少神犇?
【输入格式】
输入到mod.in
第一行2个整数n、m,分别表示图的点数和边数。
第2行到底m+1行,每行两个整数u,v,描述一条u到v的有向边。
【输出格式】
输出到mod.out
一行一个整数表示wyz最多能膜拜多少神犇。
【输入输出样例】
mod.in |
mod.out |
7 10 1 2 3 1 2 5 2 4 3 7 3 5 3 6 6 5 7 2 4 7 |
6 |
【数据范围】
对于25%的数据,保证n<=100,m<=250,
对于43.75%的数据,保证n<=3,000,m<=7,000。
对于100%的数据,保证n,m<=100,000。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define N 100005 #define M 100005 struct edge{int from,adj,next;}e[M],e0[M]; int n,m,stamp=0,top=0,cnt=0,qhead,qtail; int dfn[N],g[N],color[N],size[N],low[M],stk[N]; int g0[N],degree[N],degree0[N],q[N],f[N],f0[N]; void dfs(int u) { dfn[u]=low[u]=++stamp; stk[top++]=u; for(int i=g[u];i;i=e[i].next) { int v=e[i].adj; if(dfn[v]&&!color[v])low[u]=min(low[u],dfn[v]); if(!dfn[v]) { dfs(v); low[u]=min(low[u],low[v]); } } if(low[u]==dfn[u]) { ++cnt; while(stk[top]!=u) { color[stk[--top]]=cnt; size[cnt]++; } } } void bfs(int s) { memset(f,0,sizeof(f)); qhead=qtail=0; for(int i=1;i<=cnt;i++) if(!degree[i])q[++qtail]=i; f[s]=size[s]; while(qhead<qtail) { int u=q[++qhead]; for(int i=g[u];i;i=e[i].next) { int v=e[i].adj; if(f[u])f[v]=max(f[v],f[u]+size[v]); if(!--degree[v])q[++qtail]=v; } } } void bfs0(int s) { memset(f0,0,sizeof(f0)); qhead=qtail=0; for(int i=1;i<=cnt;i++) if(!degree0[i])q[++qtail]=i; f0[s]=size[s]; while(qhead<qtail) { int u=q[++qhead]; for(int i=g0[u];i;i=e0[i].next) { int v=e0[i].adj; if(f0[u])f0[v]=max(f0[v],f0[u]+size[v]); if(!--degree0[v])q[++qtail]=v; } } } int main() { freopen("mod.in","r",stdin); freopen("mod.out","w",stdout); scanf("%d%d",&n,&m); memset(g,0,sizeof(g)); for(int i=1;i<=m;i++) { scanf("%d%d",&e[i].from,&e[i].adj); e[i].next=g[e[i].from]; g[e[i].from]=i; } memset(dfn,0,sizeof(dfn)); memset(color,0,sizeof(color)); memset(size,0,sizeof(size)); for(int i=1;i<=n;i++) if(!dfn[i])dfs(i); int m0=0,s=color[1]; memset(g,0,sizeof(g)); memset(g0,0,sizeof(g0)); memset(degree,0,sizeof(degree)); memset(degree0,0,sizeof(degree0)); for(int i=1;i<=m;i++) if(color[e[i].from]!=color[e[i].adj]) { ++m0; e[m0].from=color[e[i].from]; e[m0].adj=color[e[i].adj]; e[m0].next=g[e[m0].from]; g[e[m0].from]=m0; ++degree[e[m0].adj]; e0[m0].from=e[m0].adj; e0[m0].adj=e[m0].from; e0[m0].next=g0[e0[m0].from]; g0[e0[m0].from]=m0; ++degree0[e0[m0].adj]; } bfs(s);bfs0(s); int ans=size[s]; for(int i=1;i<=m0;i++) if(f[e0[i].from]&&f0[e0[i].adj]) ans=max(ans,f[e0[i].from]+f0[e0[i].adj]-size[s]); printf("%d\n",ans); fclose(stdin);fclose(stdout); return 0; }
换数游戏
(game.cpp/c/pas)
【问题描述】
咸鱼wyz最近沉迷于一款游戏,叫做换数游戏。
游戏开始时,有n个1到40之间的整数排成一排。wyz每次可以将两个相邻的相等的正整数替换成一个比原数大一的正整数(需要注意的是,合并后的数可以大于40)。
wyz可以在任意时刻结束游戏。结束时wyz的得分为所有剩余的数中最大的数。
现在给定一个初始局面,你想知道wyz能获得的最高得分。
【输入格式】
输入到game.in
第一行一个正整数n。
第2行到第n+1行每行一个正整数,描述第i个数a[i]。
【输出格式】
输出到game.out
一行一个整数表示wyz能够获得的最高得分。
【输入输出样例】
game.in |
game.out |
4 1 1 1 2 |
3 |
【数据范围】
对于6.25%的数据,保证n<=5。
对于12.5%的数据,保证n<=20。
对于43.75%的数据,保证n<=1024。
对于100%的数据,保证n<=262144。
数据保证1<=a[i]<=40。
#include<cstdio> #include<cstring> #define N 300005 int ans=0,a[N],n,nxt[N]; int main() { freopen("game.in","r",stdin); freopen("game.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); memset(nxt,0,sizeof(nxt)); for(int k=1;k<=60;k++) for(int i=1;i<=n;i++) if(a[i]==k)nxt[i]=i+1,ans=k; else if(nxt[i]&&nxt[nxt[i]])nxt[i]=nxt[nxt[i]],ans=k; else nxt[i]=0; printf("%d\n",ans); fclose(stdin);fclose(stdout); return 0; }