1. 程式人生 > >模擬題1

模擬題1

div 優化 需要 adding freopen 多少 clas 一個人 mem

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;
}

模擬題1