• 20180303开学测总结


    上上周进行了开学测,现在补上一篇题解

    难度不算太大,但只有2h,所以时间比较紧,本来老师要求初二的只做T3T4,但我也还是都打完了。

     

    1、成绩(score)

    【题目描述】

     

    分析:

     

    这道题一看感觉好熟悉,没错就是NOIP2017 普及的T1,所以5分钟的问题,随随便便A掉。

     

    代码:

     

     1 #include<cstdio>
     2 using namespace std;
     3 int a,b,c;
     4 int main()
     5 {
     6     freopen("score.in","r",stdin);
     7     freopen("score.out","w",stdout);
     8     scanf("%d%d%d",&a,&b,&c);
     9     printf("%d",a/5+b/10*3+c/2);
    10     fclose(stdin);
    11     fclose(stdout);
    12     return 0;
    13 }

     

    得分:100

     

     

     

    2、程序员输入问题(editor)

     

    【题目描述】

    程序员输入程序,出现差错时可以采取以下的补救措施:敲错了一个键时,可以补敲一个退格符“#”,以表示前一个字符无效;发现当前一行有错,可以敲入一个退行符“@”,以表示“@”与前一个换行符之间的字符全部无效。如:在终端上输入了这样两行字符:

    PRKJ##OGRAN#M LX;

    VAR@CONST N:#=10;

    则实际有效的是:

    PROGRAM LX;

    CONST N=10;

     

    【输入格式】

    editor.in 输入一行字符,个数不超过100

     

    【输出格式】

    editor.out 输出一行字符,表示实际有效字符

     

    【输入样例】

    sdfosif@for(ii#=1,#;i<.#=8;i+++#);

     

    【输出样例】

    for(i=1;i<=8;i++);

     

    分析:

    这是一道字符串的处理题,因为是最后十分钟才做的,所以没有检查,没有推敲,其实用栈来解决非常方便,当时可能打漏了一点条件吧,所以wa了两个点。

     

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 using namespace std;
     5 
     6 int len,last,top;
     7 char a[150],b[150];
     8 
     9 int main()
    10 {
    11     int i,j;
    12     gets(a);
    13     len=strlen(a);
    14     for (i=0;i<len;i++)
    15         if (a[i]=='@')
    16             last=i;
    17     for (i=last+1;i<len;i++)
    18     {
    19         if (a[i]!='#')
    20             b[++top]=a[i];
    21         else
    22             --top;
    23     }
    24     for (i=1;i<=top;i++)
    25         putchar(b[i]);
    26     return 0;
    27 }

    得分:80

     

     

     

    3、滑动的窗户(window)

     

    【题目描述】

    在一个包含n个元素的数组上,有一个长度为k的窗户在从左向右滑动。窗户每滑动到一个位置,我们都可以看到k个元素在窗户中。如下的例子所示,假设数组为 [1 3 -1 -3 5 3 6 7],而k等于3:

    对于窗户滑动过的每个位置,请给出窗户内k个元素的最小值和最大值。

     

    【输入格式】 window.in

    输入的第一行包括两个整数n,k,n表示数组的长度,k表示窗户的长度。

    接下来一行包括n个整数,表示这个n个元素的数组。

     

    【输出格式】window.out

    输出包含两行,每行包括n-k+1个整数,第一行表示窗户从左到右滑动过程中的最小值,第二行表示窗户从左到右滑动过程中的最大值。

     

    【输入样例】

    8 3

    1 3 -1 -3 5 3 6 7

     

    【输出样例】

    -1 -3 -3 -3 3 3

    3 3 5 5 6 7

     

    【数据范围】

    对于100%的数据,3<=n<=1000000,1<=k<=n,数组中每个元素均在int范围内。

     

    分析:

     

    这道题但是一看感觉是一道单调队列的题,很模板,但是我也好像没有正式地打过一遍单调队列(好像唯一一次是在寒假打的),所以我有点怂,先打了一个RMQ的st表,以防万一,也用作对拍,然后花了一个多小时手推单调队列,写了个山寨版的单调,但还是a过去了。

     

    代码:

     

    RMQ对拍:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<cctype>
     5 using namespace std;
     6 
     7 const int size=1000010;
     8 int n,k,a[size],log[60],f[size][40],g[size][40];
     9 
    10 inline int read()
    11 {
    12     int x=0,flag=1;
    13     char c=getchar();
    14     while (!isdigit(c))
    15         flag=c=='-'?-1:1,c=getchar();
    16     while (isdigit(c))
    17         x=(x<<1)+(x<<3)+(c^48),c=getchar();
    18     return x*flag;
    19 }
    20 
    21 inline void dolog()
    22 {
    23     int i;
    24     log[0]=-1;
    25     for (i=1;i<=40;i++)
    26         log[i]=log[i>>1]+1;
    27 }
    28 
    29 inline void init()
    30 {
    31     int i,j;
    32     for (i=1;i<=n;i++)
    33         f[i][0]=a[i],g[i][0]=a[i];
    34     for (j=1;j<=log[n];j++)
    35         for (i=1;i<=n;i++)
    36         {
    37             f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
    38             g[i][j]=min(g[i][j-1],g[i+(1<<j-1)][j-1]);
    39         }
    40 }
    41 
    42 inline int getmax(int l,int r)
    43 {
    44     int k=log[r-l+1];
    45     return max(f[l][k],f[r-(1<<k)+1][k]);
    46 }
    47 
    48 inline int getmin(int l,int r)
    49 {
    50     int k=log[r-l+1];
    51     return min(g[l][k],g[r-(1<<k)+1][k]);
    52 }
    53 
    54 int main()
    55 {
    56 //    freopen("window.in","r",stdin);
    57 //    freopen("window.out","w",stdout);
    58     int i,j;
    59     n=read();
    60     k=read();
    61     for (i=1;i<=n;i++)
    62         a[i]=read();
    63     dolog();
    64     init();
    65     printf("%d",getmin(1,k));
    66     for (i=2;i<=n-k+1;i++)
    67         printf(" %d",getmin(i,i+k-1));
    68     printf("
    %d",getmax(1,k));
    69     for (i=2;i<=n-k+1;i++)
    70         printf(" %d",getmax(i,i+k-1));
    71     fclose(stdin);
    72     fclose(stdout);
    73     return 0;
    74 }

     

    山寨单调队列:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<cctype>
     5 using namespace std;
     6 
     7 const int size=1000010;
     8 int n,k,a[size],f[size*3],g[size*3],l,r,flag;//f:min,g:max
     9 
    10 inline int read()
    11 {
    12     int x=0,flag=1;
    13     char c=getchar();
    14     while (!isdigit(c))
    15         flag=c=='-'?-1:1,c=getchar();
    16     while (isdigit(c))
    17         x=(x<<1)+(x<<3)+(c^48),c=getchar();
    18     return x*flag;
    19 }
    20 
    21 int main()
    22 {
    23     freopen("window.in","r",stdin);
    24     freopen("window.out","w",stdout);
    25     int i,j;
    26     n=read();
    27     k=read();
    28     for (i=1;i<=n;i++)
    29         a[i]=read();
    30     l=1,r=0;
    31     f[++r]=1;
    32     flag=0;
    33     for (i=1;i<=n;i++)
    34     {
    35         while (f[l]<i-k+1)
    36             l++;
    37         while (l<r&&a[f[l]]>=a[f[r]])
    38             l++;
    39         if (i>=k)
    40         {
    41         if (flag==0)
    42             printf("%d",a[f[l]]),flag=1;
    43         else
    44             printf(" %d",a[f[l]]);
    45         }
    46         while (r>l&&a[i+1]<=a[f[r]])
    47             r--;
    48         f[++r]=i+1;
    49     }
    50     printf("
    ");
    51     flag=0;
    52     l=1,r=0;
    53     g[++r]=1;
    54     for (i=1;i<=n;i++)
    55     {
    56         while (g[l]<i-k+1)
    57             l++;
    58         while (l<r&&a[g[l]]<=a[g[r]])
    59             l++;
    60         if (i>=k)
    61         {
    62         if (flag==0)
    63             printf("%d",a[g[l]]),flag=1;
    64         else
    65             printf(" %d",a[g[l]]);
    66         }
    67         while (r>l&&a[i+1]>=a[g[r]])
    68             r--;
    69         g[++r]=i+1;
    70     }
    71     fclose(stdin);
    72     fclose(stdout);
    73     return 0;
    74 }

     

    得分:100

     

     

     

    4、蒸发学水(water)

     

    【题目描述】

    众所周知,TerryHu 是一位大佬,他平时最喜欢做的事就是蒸发学水。 机房的位置一共有n 行m 列,一开始每个位置都有一滴学水,TerryHu 决定在每一个时刻选择一滴学水进行蒸发,直到机房里不再存在学水。 TerryHu 想知道在每个时刻之后,机房里剩下的学水构成了几个联通块。

     

    【输入格式】water.in

    第一行包含2 个正整数n,m。 之后n 行每行包含m 个正整数Aij,表示第i 行第j 列的学水在时刻Aij 被蒸发,保证{A}构成了一个n *m 的排列。

     

    【输出格式】water.out

    共n * m 行每行包含1 个整数ansi,时刻i 之后剩下的学水构成的联通块的数量。

     

    【输入样例】

    2 2

    1 3

    4 2

     

    【输出样例】

    1

    2

    1

    0

     

    【数据范围】

    对于60% 的数据:n,m<= 50; 对于100% 的数据:n,m<= 1000。

     

    分析:

    这道题的正解应该是并查集,通过从后往前推的一个过程,判断当前节点的上下左右分别构不构成联通块,从而解决。考试时没时间了,所以打了个暴力,但是不知道为什么拿不完60分。

     

    代码:

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 
     8 const int size=1010;
     9 int n,m,ans,tot;
    10 int x[5]={0,0,1,0,-1},y[5]={0,-1,0,1,0};
    11 bool map[size][size],run[size][size];
    12 struct node
    13 {
    14     int val,x,y;
    15 }a[size*size];
    16 
    17 inline int read()
    18 {
    19     int x=0,flag=1;
    20     char c=getchar();
    21     while (!isdigit(c))
    22         flag=c=='-'?-1:1,c=getchar();
    23     while (isdigit(c))
    24         x=(x<<1)+(x<<3)+(c^48),c=getchar();
    25     return x*flag;
    26 }
    27 
    28 bool comp(node a,node b)
    29 {
    30     return a.val<b.val;
    31 }
    32 
    33 void dfs(int xx,int yy)
    34 {
    35     int i;
    36     for (i=1;i<=4;i++)
    37         if (map[xx+x[i]][yy+y[i]]==0&&run[xx+x[i]][yy+y[i]]==0&&xx+x[i]>=1&&xx+x[i]<=m&&yy+y[i]>=1&&yy+y[i]<=n)
    38         {
    39             run[xx+x[i]][yy+y[i]]=1;
    40             dfs(xx+x[i],yy+y[i]);
    41         }
    42 }
    43 
    44 int main()
    45 {
    46     freopen("water.in","r",stdin);
    47     freopen("water.out","w",stdout);
    48     int i,j,k;
    49     n=read(),m=read();
    50     for (i=1;i<=n;i++)
    51         for (j=1;j<=m;j++)
    52         {
    53             a[++tot].val=read();
    54             a[tot].x=i;
    55             a[tot].y=j;
    56         }
    57     sort(a+1,a+tot+1,comp);
    58     for (i=1;i<=tot;i++)
    59     {
    60         ans=0;
    61         memset(run,0,sizeof(run));
    62         map[a[i].x][a[i].y]=1;
    63         for (k=1;k<=n;k++)
    64             for (j=1;j<=m;j++)
    65                 if (map[k][j]==0&&run[k][j]==0)
    66                     ans++,dfs(k,j);
    67         printf("%d
    ",ans);
    68     }
    69     fclose(stdin);
    70     fclose(stdout);
    71     return 0;
    72 }

     

    正解:

     

     1 #include<cstdio> 
     2 #include<cctype> 
     3 using namespace std; 
     4   
     5 int father[1000010],n,m,a[1010][1010],ans[1000010],x[1000010],y[1000010]; 
     6   
     7 int find(int x) 
     8 { 
     9     if (father[x]!=x) 
    10         father[x]=find(father[x]); 
    11     return father[x]; 
    12 } 
    13   
    14 int read() 
    15 { 
    16     int x=0,f=1; 
    17     char c=getchar(); 
    18     while (!isdigit(c)) 
    19         f=c=='-'?-1:1,c=getchar(); 
    20     while (isdigit(c)) 
    21         x=(x<<1)+(x<<3)+(c^48),c=getchar(); 
    22     return x*f; 
    23 } 
    24   
    25 int main() 
    26 { 
    27     int i,j; 
    28 //  n=read(); 
    29 //  m=read(); 
    30     scanf("%d%d",&n,&m); 
    31     for (i=1;i<=n;i++) 
    32         for (j=1;j<=m;j++) 
    33         { 
    34             scanf("%d",&a[i][j]); 
    35             x[a[i][j]]=i; 
    36             y[a[i][j]]=j; 
    37             father[a[i][j]]=a[i][j]; 
    38         } 
    39     for (i=n*m;i>=1;i--) 
    40     { 
    41         ans[i]=ans[i+1]+1; 
    42         int t,p; 
    43         t=find(i),p=find(a[x[i]-1][y[i]]); 
    44         if (t&&p&&t!=p&&a[x[i]-1][y[i]]>i) 
    45             father[t]=p,ans[i]--; 
    46         t=find(i),p=find(a[x[i]+1][y[i]]); 
    47         if (t&&p&&t!=p&&a[x[i]+1][y[i]]>i) 
    48             father[t]=p,ans[i]--; 
    49         t=find(i),p=find(a[x[i]][y[i]-1]); 
    50         if (t&&p&&t!=p&&a[x[i]][y[i]-1]>i) 
    51             father[t]=p,ans[i]--; 
    52         t=find(i),p=find(a[x[i]][y[i]+1]); 
    53         if (t&&p&&t!=p&&a[x[i]][y[i]+1]>i) 
    54             father[t]=p,ans[i]--; 
    55     } 
    56     for (i=2;i<=n*m+1;i++) 
    57         printf("%d
    ",ans[i]); 
    58     return 0; 
    59 } 

     

    得分:30

     

    总分:

    100+80+100+30=310

     

    总结:

    总体都很水,可以算得上是NOIP普及组比较简单的那种总难度。

    但是我感觉有失误,首先T2不应该错,假如给多1h,我可能可以A过T4,但时间就还是有点短啊。

  • 相关阅读:
    nproc 查看系统可用处理单元数
    c++内存泄露的坑
    内存泄露脚本
    c++内存问题(转)
    tmp
    kprobe
    内存对齐算法
    正则
    P3261 [JLOI2015]城池攻占有趣的做法
    CF1620C BAString题解
  • 原文地址:https://www.cnblogs.com/Ronald-MOK1426/p/8585300.html
Copyright © 2020-2023  润新知