NOIP模拟题 10.31

T1 Mushroom的序列

【问题描述】

Mushroom手中有n个数排成一排,现在Mushroom想取一个连续的子序列,使得这个子序列满足:最多只改变一个数,使得这个连续的子序列是严格上升子序列,Mushroom想知道这个序列的最长长度是多少。

【输入格式】

第一行一个整数n,表示有n个数。
第二行为n个数。

【输出格式】

一个数,为最长长度。

【输入样例】

6
7 2 3 1 5 6

【输出样例】

5

【样例解释】

选择第2个数到第6个数,把1改变成4即可。

【数据范围】

对于30%的数据,n<=10
对于60%的数据,n<=1000
对于100%的数据,n<=100000

这道题可以直接从头到尾扫一遍,判断情况。我用的是两边扫一遍,然后判断是否可以改。水题,不说了。
代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int a[100002],f[100002],g[100002],ans;
inline int read()
{
    static int r,sign;
    static char c;
    r=0,sign=1;
    do c=getchar();while(c!='-'&&(c<'0'||c>'9'));
    if(c=='-')sign=-1,c=getchar();
    while(c>='0'&&c<='9')r=r*10+(int)(c-'0'),c=getchar();
    return sign*r;
}
int main()
{
    freopen("seq.in","r",stdin);
    freopen("seq.out","w",stdout);
    int n=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    f[1]=1;g[n]=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>a[i-1])
            f[i]=f[i-1]+1;
        else f[i]=1;
    }
    for(int i=n-1;i>=1;i--)
    {
        if(a[i]<a[i+1])
            g[i]=g[i+1]+1;
        else g[i]=1;
    }
    for(int i=1;i<=n;i++)
    {
        if(i-f[i]>=1)
            ans=max(ans,f[i]+1);
        else ans=max(ans,f[i]);
        if(i+g[i]<=n)
            ans=max(ans,g[i]+1);
        else ans=max(ans,g[i]);
    }
    for(int i=1;i<=n-2;i++)
        if(a[i]<=a[i+2]-2)
            ans=max(ans,1+f[i]+g[i+2]);
    printf("%d",ans);
    return 0;
}

T2 Mushroom的区间

【题目描述】

Mushroom有一行数,初始时全部是0。现在Mushroom有m个区间[L,R],他希望用以下操作得到新的序列。
从m个给定区间中选择一个区间[s,t],把区间中的数对应元素全部翻转。(0变1,1变0)
请告诉Mushroom他能得到多少区间。(模10^9+7)

【输入格式】

第一行包含两个整数n,m。表示n个数和m个区间。
接下来m行是所表示的区间。

【输出格式】

一个整数,表示能得到的区间数。

【样例输入】

3 3
1 1
2 2
3 3

【样例输出】

8

【数据范围】

对于30%的数据,n,m<=20
对于60%的数据,n,m<=100
对于100%的数据,n,m<=100000

【样例解释】

每个位置都可以单个修改,所以有8种可能。

朴素想法是用二进制数保存状态,但貌似30%都没法过,因为20的阶乘还是蛮大的,但数据水…过了前三组…
有人用搜索A了。首先答案是2^m,考虑到只有可能大区间包含小区间,如果一个大区间可以由几个小区间组成,那么m就要减1。将每个区间左开右闭或者坐闭右开来储存,将结构体按区间长度来排序,每枚举一个区间dfs区间的开头,如果搜到的边界搜过,m-=1。本来应该是过不完的,但数据水…
正解思想如上,但是妙用并查集,将区间开头结尾用并查集储存起来,每枚举一个区间,如果区间两端祖先相同,m-=1。
代码:

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int mod=1e9+7;
int x,y,n,m,f[200005],ans=1;
inline int read()
{
    static int r,sign;static char c;
    r=0,sign=1;
    do c=getchar();while(c!='-'&&(c<'0'||c>'9'));
    if(c=='-')sign=-1,c=getchar();
    while(c>='0'&&c<='9')r=r*10+(int)(c-'0'),c=getchar();
    return sign*r;
}
int find(int x)
{
    if(f[x]==x)
        return x;
    return f[x]=find(f[x]);
}
int main ()
{
    freopen("seg.in","r",stdin);
    freopen("seg.out","w",stdout);
    n=read();m=read();
    for(int i=0;i<=n;i++)
        f[i]=i;
    for(int i=1;i<=m;i++)
    {
        x=read();y=read();
        int fx=find(x-1);
        int fy=find(y);
        if(fx!=fy)
        {
            ans=(ans<<1)%mod;
            f[fx]=fy;
        }
    }
    printf("%d\n",ans);
    return 0;
}

T3 来自风平浪静的明天

【题目描述】

冬眠了五年,光终于从梦中醒来。
千咲、要,大家都在。
隐约记得“昨天”的海船祭,爱花意外成为贡女,沉入海底。
海面冰封,却有丝丝暖流在冰面之下涌动。
此时,爱花沉睡在祭海女神的墓地。她的胞衣在一点点脱落,化作一簇簇暖流,夹杂着她的感情,向海面上涌去。
爱花,你在哪里?
五年之后,纺已经成为海洋学研究科的大学生。
在纺的帮助下,光得知了海面下海流的情况。
纺告诉光,暖流一旦产生,就会不断地向四周扩散,直到遇到海中的岩石。
红腹海牛,快告诉光,爱花在哪里。
纺帮你绘制了一张海流情况图,长度为N,宽度为M。
海很大,一边有沙滩,一边一望无际,但长度和宽度都不会超过300。沙滩是金黄色的,所以用Y表示。海是蓝色的,所以用B表示。暖流很暖和,所以用H表示
海中有大大小小的石头。石头很危险,所以用X表示
光相信自己一定能找到爱花(爱花的位置只有一种可能)

【输入格式】

第一行包括两个整数N,M。
接下来N行,每行M个字符。

【输出格式】

仅一行,表示爱花的位置(如果你无能为力,请输出 -1 ,只要你尽力,光不会责怪你)

【样例输入】

5 5
YYYHB
YYHHH
YHHXB
BBHBB
BBBBB

【样例输出】

2 3

【数据范围】

对于30%的数据,n,m<=10
对于70%的数据,n,m<=100
对于100%的数据,n,m<=300

【样例解释】

在(2,3)出现第一个H后,经过3s后,出现样例输入的地图。
P.S. Mushroom拜托他GF出的这题= =

表示一开始没有读懂题…
题意就是从一个 H 出发,在碰到 B 之前能够将所有的 H 遍历,这个 H 就是答案。
朴素想法用bfs搜就是。数据水,只有倒数第二个点要T…
正解没有写,使用dp做的。
bfs:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
    int xx,yy;
}gg[90003];
int x[4]={0,0,1,-1},y[4]={1,-1,0,0};
char map[302][302];
int bcnt,n,m,num[90003][2],ord[90003],tot;
bool judge[302][302];
bool bfs(int i,int j)
{
    ord[1]=1;
    tot=1;
    queue<node>q;
    node o;
    o.xx=i;
    o.yy=j;
    q.push(o);
    int step=1,coun=0,pre=0,time=0x7f7f7f7f;
    bool bbbb=false;
    while(!q.empty())
    {
        node u=q.front();
        q.pop();
        if(pre==ord[tot])
        {
            bbbb=false;
            ord[++tot]=coun;
            coun=0;
            pre=0;
        }
        if(step==bcnt)
            return true;
        pre++;
        for(int k=0;k<=3;k++)
        {
            int ox=u.xx+x[k],oy=u.yy+y[k];
            if(ox>=1&&ox<=n&&oy>=1&&oy<=m&&!judge[ox][oy])
            {
                if(map[ox][oy]=='H')
                {
                    if(tot-1>time)
                        return false;
                    node t;t.xx=ox;t.yy=oy;q.push(t);
                    step++;coun++;
                    judge[ox][oy]=true;
                }
                else if(map[ox][oy]=='B')
                    time=tot-1;
            }
        }
    }
    if(step==bcnt)
        return true;
}
int main()
{
    freopen("calm.in","r",stdin);
    freopen("calm.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        getchar();
        for(int j=1;j<=n;j++)
        {
            scanf("%c",&map[i][j]);
            if(map[i][j]=='H')
            {
                num[++bcnt][0]=i;
                num[bcnt][1]=j;
            }
        }
    }
    for(int i=1;i<=bcnt;i++)
    {
        judge[num[i][0]][num[i][1]]=true;
        int l=num[i][0],r=num[i][1];
        if(bfs(num[i][0],num[i][1]))
        {
            printf("%d %d",num[i][0],num[i][1]);
            return 0;
        }
        memset(judge,false,sizeof judge);
        memset(ord,0,sizeof ord);
    }
    printf("-1");
    return 0;
}

标答正解:

#include <cstdio>
#include <iostream>
#define INF 300
#include <algorithm>
using namespace std;
char Map[INF+1][INF+1];
bool Find[2*INF+1][INF+1][INF+1];
bool Flow[2*INF+1][INF+1][INF+1];
int N,M;
bool LoveFlower(int Deep,int X,int Y)
{
    if (0==X) return true;
    if (0==Y) return true;
    if (N+1==X) return true;
    if (M+1==Y) return true;
    if (Map[X][Y]!='H') return true;
    if (Find[Deep][X][Y]) return Flow[Deep][X][Y];
    if (0==Deep)
    {
        Find[Deep][X][Y]=true;
        Flow[Deep][X][Y]=(Map[X][Y]=='H');
        return Flow[Deep][X][Y];
    }
    if ('B'==Map[X-1][Y]||'B'==Map[X+1][Y]||'B'==Map[X][Y-1]||'B'==Map[X][Y+1])
    {
        Find[Deep][X][Y]=true;
        Flow[Deep][X][Y]=false;
        return Flow[Deep][X][Y];
    }
    Find[Deep][X][Y]=true;
    Flow[Deep][X][Y]=LoveFlower(Deep-1,X-1,Y)&&LoveFlower(Deep-1,X+1,Y)&&LoveFlower(Deep-1,X,Y-1)&&LoveFlower(Deep-1,X,Y+1);
    return Flow[Deep][X][Y];
}
char T[INF+1];
int main()
{
    freopen("Calm.in","r",stdin);
    freopen("Calm.out","w",stdout);
    scanf("%d%d",&N,&M);
    for (int i=1;i<=N;i++)
    {
        scanf("%s",T);
        for (int j=1;j<=M;j++)
            Map[i][j]=T[j-1];
    }
    for (int i=1;i<=N+M;i++)
        for (int j=1;j<=N;j++)
            for (int k=1;k<=M;k++)
                if (Map[j][k]=='H')
                LoveFlower(i,j,k);
    for (int i=N+M;i>=1;i--)
        for (int j=1;j<=N;j++)
            for (int k=1;k<=M;k++)
                if (Flow[i][j][k])
                {
                    cout<<j<<" "<<k<<'\n';
                    return 0;
                }

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值