• FJUTOJ-周赛2016-11-25


    注:fjutoj基本每周都有一次周赛,欢迎大家都来参加!

    网址:http://59.77.139.92/ 或 acm.fjut.edu.cn

    A题

    题意:一年中,每个月有可能亏x 元,有可能赚y 元,每连续的五个月加起来都亏钱,问一年最多赚多少钱,如果不能赚钱,输出"Deficit"。

    思路:

      贪心的思路,五个月中亏钱的月份放后面去,并且使得五个月加起来亏钱最少,因此共有4种情况:

      x y y y y x y y y y x y

      x x y y y x x y y y x x

      x x x y y x x x y y x x

      x x x x y x x x x y x x

      用if判断一下即可

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 #include<math.h>
     5 #include<set>
     6 #include<map>
     7 #include<list>
     8 #include<stack>
     9 #include<queue>
    10 #include<vector>
    11 #include<string>
    12 #include<iostream>
    13 #include<algorithm>
    14 using namespace std;
    15 #define lson rt<<1
    16 #define rson rt<<1|1
    17 #define N 100010
    18 #define M 100010
    19 #define Mod 1000000007
    20 #define LL long long
    21 #define INF 0x7fffffff
    22 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
    23 #define For(i,f_start,f_end) for(int i=f_start;i<f_end;i++)
    24 #define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--)
    25 #define Rep(i,f_end,f_start) for(int i=f_end;i>f_start;i--)
    26 #define MT(x,i) memset(x,i,sizeof(x))
    27 #define gcd(x,y) __gcd(x,y)
    28 const double PI = acos(-1);
    29 
    30 int main()
    31 {
    32   int x,y;
    33   while(scanf("%d%d",&x,&y)!=EOF)
    34   {
    35     if(x>=4*y) printf("Deficit
    ");
    36     else if(2*x>3*y)
    37     {
    38       if(3*x<=9*y) printf("Deficit
    ");
    39       else printf("%d
    ",3*x-9*y);
    40     }
    41     else if(3*x>=2*y)
    42     {
    43       if(6*x<=6*y) printf("Deficit
    ");
    44       else printf("%d
    ",6*x-6*y);
    45     }
    46     else if(4*x>=y)
    47     {
    48       if(8*x<=4*y) printf("Deficit
    ");
    49       else printf("%d
    ",8*x-4*y);
    50     }
    51     else
    52     {
    53       if(10*x<=2*y) printf("Deficit
    ");
    54       else printf("%d
    ",10*x-2*y);
    55     }
    56   }
    57   return 0;
    58 }
    A题AC代码

    B题

    题意:规定了两种日历的格式,给出第一个日历日期,要求转化成第二种。

    思路:简单题,考验新生的代码实现能力,并不需要什么思路,略过。

     1 #include<stdio.h>
     2 #include<map>
     3 #include<string>
     4 #include<iostream>
     5 using namespace std;
     6 
     7 map<string, int> mp;
     8 map<int, string> pm;
     9 int main()
    10 {
    11   mp["pop"]=0; mp["no"]=1; mp["zip"]=2;
    12   mp["zotz"]=3; mp["tzec"]=4; mp["xul"]=5;
    13   mp["yoxkin"]=6; mp["mol"]=7; mp["chen"]=8;
    14   mp["yax"]=9; mp["zac"]=10; mp["ceh"]=11;
    15   mp["mac"]=12; mp["kankin"]=13; mp["muan"]=14;
    16   mp["pax"]=15; mp["koyab"]=16; mp["cumhu"]=17;
    17   mp["uayet"]=18;
    18 
    19   pm[0]="imix"; pm[1]="ik"; pm[2]="akbal"; pm[3]="kan"; pm[4]="chicchan"; pm[5]="cimi";
    20   pm[6]="manik"; pm[7]="lamat"; pm[8]="muluk"; pm[9]="ok"; pm[10]="chuen"; pm[11]="eb";
    21   pm[12]="ben"; pm[13]="ix"; pm[14]="mem"; pm[15]="cib"; pm[16]="caban"; pm[17]="eznab";
    22   pm[18]="canac"; pm[19]="ahau";
    23 
    24   int t;
    25   scanf("%d",&t);
    26   printf("%d
    ",t);
    27   while(t--)
    28   {
    29     int day=0, mon, year;
    30     string tmp;
    31     scanf("%d.",&day); cin>>tmp; scanf("%d",&year);
    32     mon=mp[tmp];
    33     day = year*365 + mon*20 + day;
    34     year = day/260;
    35     mon = day%20;
    36     day = day%13;
    37     printf("%d ",day+1); cout<<pm[mon]; printf(" %d
    ",year);
    38   }
    39   return 0;
    40 }
    B题AC代码

    C题

    题意:字符串比较,第一个字符串多包含了*、?,*可以替换为任意多个任意字符,?可以替换为1个任意字符。

    思路:数据量大时,用AC自动机做,因为该题数据量小,所以是简单题,递归一下更方便

     1 #include<stdio.h>
     2 using namespace std;
     3 
     4 char head[100], s[100];
     5 bool dfs(int i, int j)
     6 {
     7   if(head[i]==0 && s[j]==0) return true;
     8   else if(head[i]==0) return false;
     9   else if(s[j]==0)
    10   {
    11     for(;head[i]!=0 && head[i]=='*';i++);
    12     if(head[i]!=0) return false;
    13     else return true;
    14   }
    15   if('a'<=head[i] && head[i]<='z')
    16   {
    17     if(s[i]!=head[j]) return false;
    18     else return dfs(i+1, j+1);
    19   }
    20   else if(head[i]=='?') return dfs(i+1, j+1);
    21   else
    22   {
    23     int k;
    24     for(k=i;head[k];k++)
    25     {
    26       if(head[k]!='*') break;
    27     }
    28     if(head[k]==0) return true;
    29     bool ret=false;
    30     for(;s[j] && !ret;j++)
    31     {
    32       ret=dfs(k, j);
    33     }
    34     return ret;
    35   }
    36 }
    37 
    38 int main()
    39 {
    40   while(~scanf("%s",head))
    41   {
    42     int n;
    43     scanf("%d",&n);
    44     int co=0;
    45     while(n--)
    46     {
    47       scanf("%s",s);
    48       if(dfs(0,0)) co++;
    49     }
    50     printf("%d
    ",co);
    51   }
    52   return 0;
    53 }
    C题AC代码

    D题

    题意:有一个坐标系,坐标系上有n个点,在同一行或同一列上的任意两点称为关联的,并且关联属性是可传递的,即A和B关联,B和C关联,则可认为A和C关联,现在问图中是否任意两点都是关联的。

    n>=2 && n<=50万

    每个点的坐标x、y满足 1<=x、y<=50000

    思路:并查集,横、纵坐标最多50000,可以先对所有点按横坐标排序,然后遍历一遍,如果两点横坐标相同,他们的纵坐标就是一组的。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 #define N 500010
     6 
     7 int fa[N];
     8 int find(int x)
     9 {
    10   int p=x;
    11   while(p!=fa[p]) p=fa[p];
    12   int q;
    13   while(fa[x]!=p)
    14   {
    15     q=fa[x];
    16     fa[x]=p;
    17     x=q;
    18   }
    19   return p;
    20 }
    21 void join(int x,int y)
    22 {
    23   int fx=find(x);
    24   int fy=find(y);
    25   if(fx!=fy) fa[fx]=fy;
    26 }
    27 
    28 struct Node
    29 {
    30   int x,y;
    31 }v[N];
    32 
    33 bool cmp(Node a,Node b)
    34 {
    35   if(a.x!=b.x) return a.x>b.x;
    36   else return a.y<b.y;
    37 }
    38 
    39 bool vis[N];
    40 int main()
    41 {
    42   int n;
    43   while(scanf("%d",&n)!=EOF)
    44   {
    45     memset(vis,0,sizeof(vis));
    46     for(int i=0;i<n;i++)
    47     {
    48       scanf("%d%d",&v[i].x,&v[i].y);
    49       if(v[i].y>50000) while(1);
    50       vis[v[i].y]=1;
    51     }
    52     for(int i=1;i<=50000;i++) fa[i]=i;
    53     sort(v,v+n,cmp);
    54     int prex=-1, prey=-1;
    55     for(int i=0;i<n;i++)
    56     {
    57       if(v[i].x!=prex)
    58       {
    59         prex=v[i].x;
    60         prey=v[i].y;
    61       }
    62       else
    63       {
    64         join(prey, v[i].y);
    65       }
    66     }
    67     int co=0;
    68     for(int i=1;i<=50000;i++)
    69     {
    70       if(vis[i])
    71       {
    72         if(fa[i]==i) co++;
    73       }
    74     }
    75     if(co==1) printf("YES
    ");
    76     else printf("NO
    ");
    77   }
    78   return 0;
    79 }
    D题AC代码

    E题

    题意:给n个数,有m次询问,每次询问提供一个区间[l,r],每次求一个x使得最小。

    思路:划分树,基本是模板题了,略过。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 #define N 100010
     6 #define LL long long
     7 int sorted[N];    //排序好的数组
     8 int num[20][N];   //num[i] 表示i前面有多少个点进入左孩子
     9 LL sum[20][N];
    10 int val[20][N];   //20层,每一层元素排放,0层就是原数组
    11 void build(int l,int r,int ceng)
    12 {
    13   if(l==r) return ;
    14   int mid=(l+r)/2,isame=mid-l+1;  //isame保存有多少和sorted[mid]一样大的数进入左孩子
    15   for(int i=l;i<=r;i++) if(val[ceng][i]<sorted[mid]) isame--;
    16   int ln=l,rn=mid+1;   //本结点两个孩子结点的开头,ln左
    17   for(int i=l;i<=r;i++)
    18   {
    19     if(i==l) num[ceng][i]=0, sum[ceng][i]=0;
    20     else num[ceng][i]=num[ceng][i-1], sum[ceng][i]=sum[ceng][i-1];
    21     if(val[ceng][i]<sorted[mid] || val[ceng][i]==sorted[mid]&&isame>0)
    22     {
    23       val[ceng+1][ln++]=val[ceng][i];
    24       num[ceng][i]++;
    25       sum[ceng][i]+=val[ceng][i];
    26       if(val[ceng][i]==sorted[mid]) isame--;
    27     }
    28     else
    29     {
    30       val[ceng+1][rn++]=val[ceng][i];
    31     }
    32   }
    33   build(l,mid,ceng+1);
    34   build(mid+1,r,ceng+1);
    35 }
    36 LL ans;
    37 LL look(int ceng,int sl,int sr,int l,int r,int k,LL he)
    38 {
    39   if(sl==sr) return val[ceng][sl];
    40   int ly; LL sy;
    41   if(l==sl) ly=0,sy=0;
    42   else ly=num[ceng][l-1],sy=sum[ceng][l-1];
    43   int tolef=num[ceng][r]-ly;
    44   LL ret;
    45   if(tolef>=k)
    46   {
    47     ret = look(ceng+1,sl,(sl+sr)/2,sl+ly,sl+num[ceng][r]-1,k,sum[ceng][r]-sy);
    48     ans += (he-sum[ceng][r]+sy)-ret*(r-l+1-tolef);
    49   }
    50   else
    51   {
    52     int lr = (sl+sr)/2 + 1 + (l-sl-ly);
    53     ret = look(ceng+1,(sl+sr)/2+1,sr,lr,lr+r-l+1-tolef-1,k-tolef,he-sum[ceng][r]+sy);
    54     ans += ret*tolef-sum[ceng][r]+sy;
    55   }
    56   return ret;
    57 }
    58 
    59 LL pre[N];
    60 int main()
    61 {
    62   int cas=1,t,n,m,l,r;
    63   scanf("%d",&t);
    64   while(t--)
    65   {
    66     printf("Case #%d:
    ",cas++);
    67     scanf("%d",&n);
    68     pre[0]=0;
    69     for(int i=1;i<=n;i++)
    70     {
    71       scanf("%d",&val[0][i]);
    72       sorted[i]=val[0][i];
    73       pre[i]=pre[i-1]+val[0][i];
    74     }
    75     sort(sorted+1,sorted+n+1);
    76     build(1,n,0);
    77     scanf("%d",&m);
    78     while(m--)
    79     {
    80       scanf("%d%d",&l,&r);
    81       l++, r++;
    82       ans=0;
    83       look(0,1,n,l,r,(r-l+2)/2,pre[r]-pre[l-1]);
    84       printf("%I64d
    ",ans);
    85     }
    86     printf("
    ");
    87   }
    88   return 0;
    89 }
    E题AC代码

    总结:A题考逻辑能力,B题考代码能力,C题需要更高的代码能力,D题考简单的数据结构,E题考知识面。

  • 相关阅读:
    JavaScript 数组
    Function类型
    javascript面向对象(一)
    javascript变量的作用域
    登陆验证
    注册验证
    php类
    二叉搜索树的 查询最小值
    二叉 搜索树查找最大值
    二叉搜索树 中查找是否存在该值
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/6103018.html
Copyright © 2020-2023  润新知