比赛地址:https://www.hpuoj.com/contest/16/

赛后总结:

代码基本功真的很重要!简单题总是不能一发过,模拟总是会出细节问题,debug花很长时间,天梯赛也是,大模拟总是卡在小细节上卡到心态爆炸。还是要多练,巩固基础。还有,数学好差,求极限都忘了。。。。

题目解析:

A

签到题

B

二进制转十六进制   模拟  倒着遍历  四位换一位  不足补0

代码(赛时代码 比较丑)

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
char s[maxn];
typedef struct{
    char ch[5];char c;
}node;
node a[20];
int w;
char q[maxn];
void check(int x){
    char r[5];
    r[0]=s[x-3]; r[1]=s[x-2]; r[2]=s[x-1]; r[3]=s[x];
    for(int i=1;i<=16;i++){
        if(a[i].ch[0]==r[0]&&a[i].ch[1]==r[1]&&a[i].ch[2]==r[2]&&a[i].ch[3]==r[3]){
            q[w++]=a[i].c;break;
        }
    }
    return ;
}
int T;
int main(){
    scanf("%d",&T);
    strcpy(a[1].ch,"0000");a[1].c='0';
    strcpy(a[2].ch,"0001");a[2].c='1';
    strcpy(a[3].ch,"0010");a[3].c='2';
    strcpy(a[4].ch,"0011");a[4].c='3';
    strcpy(a[5].ch,"0100");a[5].c='4';
    strcpy(a[6].ch,"0101");a[6].c='5';
    strcpy(a[7].ch,"0110");a[7].c='6';
    strcpy(a[8].ch,"0111");a[8].c='7';
    strcpy(a[9].ch,"1000");a[9].c='8';
    strcpy(a[10].ch,"1001");a[10].c='9';
    strcpy(a[11].ch,"1010");a[11].c='a';
    strcpy(a[12].ch,"1011");a[12].c='b';
    strcpy(a[13].ch,"1100");a[13].c='c';
    strcpy(a[14].ch,"1101");a[14].c='d';
    strcpy(a[15].ch,"1110");a[15].c='e';
    strcpy(a[16].ch,"1111");a[16].c='f';
    while(T--){
        scanf("%s",s);
        int l=strlen(s);
        for(int i=l-1;i>=0;){
            if(i-3>=0){check(i);i=i-4;}
            else{
               char r[5];int j;
               for(j=3;i>=0;i--){r[j]=s[i];j--;}
               while(j>=0){r[j]='0';j--;}

                for(int k=1;k<=16;k++){
                    if(a[k].ch[0]==r[0]&&a[k].ch[1]==r[1]&&a[k].ch[2]==r[2]&&a[k].ch[3]==r[3]){
                        q[w++]=a[k].c;break;
                    }
                }
            }
        }
        for(int i=w-1;i>=0;i--){
           printf("%c",q[i]);
        }
        w=0;//多组数据  需要初始化
        printf("\n");
    }
    return 0;
}

 

C

这题不难 思维题

由于障碍物不同行也不同列  所以只有下图这种 封死了的情况 才会NO

障碍物坐标排个序  判断下有没有这样的序列

代码

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int T,x,y,n,m;
typedef struct{
    int xx,yy;
}node;
node d[10007];
bool cmp(node a,node b){
    return a.xx<b.xx;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        int v[10];
        memset(v,0,sizeof(v));
        for(int i=0;i<m;i++){
            scanf("%d%d",&d[i].xx,&d[i].yy);
        }
        sort(d,d+m,cmp);
        int f=0;
        if(d[0].xx==1){
            for(int i=1;i<m;i++){
                if(d[i].xx==d[i-1].xx+1&&d[i].yy==d[i-1].yy-1){
                    if(d[i].yy==1) {
                        f=1;break;
                    }
                }
                else break;
            }
        }
        if(f==1){
            printf("No\n");
        }
        else printf("Yes %d\n",n+n-2);
    }
    return 0;
}

D

不会写

E

我开了个二维数组,52行(26+26) 两列(一个存最小距离  一个存遍历到的位置)

遍历字符串  更新每个字符的最小距离 以及位置

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
typedef long long ll;
const int maxn=1e6+7;
using namespace std;
int dp[60][3];
char s[maxn];
int v[60];
int main(){
    scanf("%s",s);
    int l=strlen(s);
    int x;
    for(int i=1;i<=52;i++)dp[i][1]=-1;
    for(int i=0;i<l;i++){

        if(s[i]>='a'&&s[i]<='z') x=s[i]-'a'+1;
        else x=s[i]-'A'+1+26;

        v[x]=1;
        if(dp[x][1]==-1) dp[x][1]=i;
        else{
            int cha=i-dp[x][1];
            if(cha<dp[x][0]||dp[x][0]==0)dp[x][0]=cha;
            dp[x][1]=i;
        }
    }
    for(int i=1;i<=52;i++){
        if(!v[i]) continue;
        if(i<=26)printf("%c:",i-1+'a');
        else printf("%c:",i-1-26+'A');
        if(dp[i][0]==0)printf("0\n");
        else{
            printf("%d\n",l-dp[i][0]);
        }
    }
    return 0;
}

F

最后还有一个半小时的时间,模拟多项式写了两遍都写炸了,可能是到最后了,脑子不清楚吧,随后这个题要补

基本功还是太差。。。

G

没看题  过的人挺多的  随后看看

H

矩形面积并   不会写 套了个板子。。。。内疚ing+自责ing

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int SIZE=505;
int add[SIZE<<2];                               
double x[SIZE<<2],sum[SIZE<<2];
struct node{
    int ss;                                     
    double l,r,h;                               
    node(){}
    node(double a,double b,double c,int d):l(a),r(b),h(c),ss(d){}
    friend bool operator<(node p,node q){       
        return p.h<q.h;
    }
}s[SIZE];
void pushup(int rt,int l,int r){
    if(add[rt])                                 
    sum[rt]=x[r+1]-x[l];                        
    else if(l==r)
    sum[rt]=0;
    else
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];            
}                                               
void update(int L,int R,int c,int l,int r,int rt){
    int m;
    if(L<=l&&r<=R){
        add[rt]+=c;                             
        pushup(rt,l,r);
        return;
    }
    m=(l+r)>>1;
    if(L<=m)
    update(L,R,c,l,m,rt<<1);
    if(R>m)
    update(L,R,c,m+1,r,rt<<1|1);
    pushup(rt,l,r);
}
int main(){                                     
    int n,i,k,l,m,r,cas; 
    double a,b,c,d,ans; 
    cas=1;  
        k=1,ans=m=0;                            
        for(i=0;i<2;i++){
            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
            x[m]=a;
            s[m++]=node(a,c,b,1);
            x[m]=c;
            s[m++]=node(a,c,d,-1);
        }
        sort(x,x+m);
        sort(s,s+m);
        for(i=1;i<m;i++)                        
        if(x[i]!=x[i-1])
        x[k++]=x[i];
        memset(add,0,sizeof(add));
        memset(sum,0,sizeof(sum));
        for(i=0;i<m-1;i++){
            l=lower_bound(x,x+k,s[i].l)-x;
            r=lower_bound(x,x+k,s[i].r)-x-1;    
            update(l,r,s[i].ss,0,k-1,1);        
            ans+=(sum[1]*(s[i+1].h-s[i].h));    
        }                                       
        printf("%.0f",ans);
    return 0; 
}

I

防AK  那没多大佬都没过  我就不用看了。。。。

J

水题  递归转预处理  O(1)查询

K

贪心

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
typedef long long ll;
const int maxn=1e5+7;
ll a[maxn];
using namespace std;
ll n,m;
int main(){
    scanf("%lld%lld",&n,&m);
    m=m*n;
    ll sum=0;
    for(int i=0;i<n;i++){
        scanf("%lld",&a[i]);
        sum+=a[i];
    }
    sort(a,a+n);
    int cnt=0;
    for(int i=0;i<n;i++){
        if(sum>=m){
            printf("%d\n",cnt);break;
        }
        sum+=1000-a[i];cnt++;
    }
    return 0;
}

L

最小生成树  Kruscal

我先把修好的边加进去  然后没修的 排序  加边并且计算权值和  最后扫一遍并查集 是不是都加进去了

wa了test19   因为  求和需要开longlong

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
#define INF 0x3f3f3f3f
int fa[maxn];
int init(int n){
    for(int i=0;i<=n;i++)fa[i]=i;
}
int Find(int x){
    return fa[x]==x?x:fa[x]=Find(fa[x]);
}
int Union(int a,int b){
    int p1=Find(a),p2=Find(b);
    fa[p2]=p1;
}
typedef struct edge{
    int from,to,val;
}dege;
edge Edge[maxn];
edge dd[maxn];
bool cmp(edge a,edge b){
    return a.val<b.val;
}
int n,m,s;
int main(){
    scanf("%d%d%d",&n,&m,&s);
    init(n);
    for(int i=0;i<m;i++){
        scanf("%d%d%d",&dd[i].from,&dd[i].to,&dd[i].val);
        Union(dd[i].from,dd[i].to);
    }
    for(int i=0;i<s;i++){
        scanf("%d%d%d",&Edge[i].from,&Edge[i].to,&Edge[i].val);
    }
    sort(Edge,Edge+s,cmp);
    ll ans=0;
    for(int i=0;i<s;i++){//依次选择最小的
        if(Find(Edge[i].from)!=Find(Edge[i].to)){
            Union(Edge[i].from,Edge[i].to);
            ans+=Edge[i].val;
        }
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(fa[i]==i)cnt++;
    }
    if(cnt>1) printf("Concubines can't do it.");
    else printf("%lld",ans);
    return 0;
}