zoukankan      html  css  js  c++  java
  • 2017.9.10所谓“切题如切菜杯”水题模拟赛(;´д`)ゞ

    T1:MHM

           LGL今天一共要上n节课,这n节课由0标号至n。由于过度劳累,除了第0节课和第n节课,LGL还打算睡上m节课,所以他做了一个睡觉计划表。通过小道消息,LGL得知WQ今天会在学校中检查,所以他想少睡k节课。但是由于某些原因,他又想使相邻的两节睡觉的课之间上的课数量的最小值最大。由于他很困,所以他请你来帮他计算这个值。

     

    输入格式:

    第一行为三个整数 n、m、k,接下来的m行为m个整数ai,表示睡觉计划表中LGL想要睡觉的课。

    输出格式:

    一个整数,表示题目所求的值。

    样例输入

    样例输出

    25 5 2

    14

    11

    17

    2

    21

    3

    样例解释:

    选择第2节和第14节不睡觉,这样子相邻的两节睡觉的课之间上的课数量的最小值为3,即第17节和第21节之间和第21节到第25节之间。没有答案更大的删除方案。

    数据范围:

    对于100%的数据:1<=n<=109,1<=k<=m<=50000,0<ai<n。

    solution:

    看题目了半天,这难道不是noip2015的跳石头的几乎是原题的变形吗。二分答案判定,废话不多说,直接上代码:

     1 #include<cstdio>
     2 int l,n,m,a[50005],L; 
     3 int check(int x) { 
     4     int last=0,ans=0; 
     5     for(int i=1;i<=n;i++){ 
     6         if(a[i]-last<x) ans++; 
     7         else last = a[i]; 
     8     } 
     9     if(ans>m)return 0; 
    10     return 1; 
    11 } 
    12 int main(){
    13     scanf("%d%d%d",&L,&n,&m); 
    14     for(int i=1;i<=n;i++) scanf("%d",&a[i]); 
    15     a[n+1]=L; n++; 
    16     int l=0,r=L; 
    17     while(l<=r) { 
    18         int mid=(l+r)/2; 
    19         if(check(mid)) l=mid+1; 
    20         else r=mid-1; 
    21     } 
    22     printf("%d
    ",l); 
    23 }

    T2:AAFA

     YYH有n道题要做。每一道题都有一个截止日期t,只要在该日期之前做完,他的父亲LRB就会奖励他w元钱。令人惊讶的是,每一道题他都只需要1秒来做。请问他最多能从父亲那里拿到多少钱?

    输入格式:

    第一行为一个整数 n,接下来的n行每一行都有两个数ti和wi,分别表示第i题的截止日期和奖励。

    输出格式:

    一个整数,表示YYH的最大获利。

    样例输入

    样例输出

    3

    2 10

    1 5

    1 7

    17

    样例解释:

                         第1秒做第3道题,第2秒做第1道题。

    数据范围:

    对于 100%的数据:1<=n、ti 、wi <=100000。

    solution:

    按截止时间排序从头往后选。选到第i个时,若已选择的题目数量小于ti,则该时间选择它一定更优;若已选择的数量等于ti,则比较第i题的收益和已选择的题目中的最小收益,在酌情选择。我没用队列维护这题10分。。。

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    typedef long long ll;
    struct work
    {
        ll d,p;
    }w[100001];
    std::priority_queue<int,std::vector<int>,std::greater<int> > q;
    int n;
    ll sz,ans;
     
    bool comp(work a,work b)
    {
        return a.d<b.d;
    }
     
    int main()
    {
        freopen("aafa.in","r",stdin);
        freopen("aafa.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%I64d%I64d",&w[i].d,&w[i].p);
        std::sort(w+1,w+1+n,comp);
        ans=0;
        for(int i=1;i<=n;i++)
        {
            sz=q.size();
            if(sz<w[i].d) q.push(w[i].p);
            else if(sz==w[i].d)
            {
                if(q.top()<w[i].p)
                {
                    q.pop();
                    q.push(w[i].p);
                }
            }
        }
        ans=0;
        while(!q.empty())
        {
            ans+=q.top();
            q.pop();
        }
        printf("%I64d",ans);
        return 0;
    }

    T3:ZZI

           YYH拿到了父亲给的钱欣喜若狂,把这些钱拿来造了n栋房子。现在他要给这些房子通电。他有两种方法:第一种是在房间里搭核电发电机发电,对于不同的房子,他需要花不同的代价Vi;,第二种是将有电的房子i的电通过电线通到没电的房子j中,这样子他需要花的代价为aij。他现在请你帮他算出他最少要花多少钱才能让所有的房子通上电。

    输入格式:

    第一行为一个整数 n。接下来的n行为 n 个整数vi,再接下来的n行每行n个数,第i行第j列的数表示aij

    输出格式:

    一个整数,表示最小代价。

    样例输入

    样例输出

    4
    5

    4

    4

    3
    0 2 2 2
    2 0 3 3
    2 3 0 4
    2 3 4 0

    9

    样例解释:

    在第4栋房子造核电发电机,再将其他三栋房子通过电线连向它。

    数据范围:

    对于 100%的数据:1<=n<=300,1<=vi,aij<=100000,保证aii=0,aij=aji

    solution: 

    几乎裸最小生成树,prim算法,具体参考[USACO Oct08] 挖水井 。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,dis[305],e[305][305],t,w,ans;
    bool flag;
    int main(){
        freopen("zzi.in","r",stdin);
        freopen("zzi.out","w",stdout);
        scanf("%d",&n);
        dis[0]=(1<<30);
        for(int i=1;i<=n;i++){
            scanf("%d",&dis[i]);
            if(dis[i]<dis[0]){
                dis[0]=dis[i];
                t=i;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&e[i][j]);
            }
        }
        ans+=dis[0];
        dis[t]=0;
        for(int j=1;j<=n;j++){
            if(dis[j]>e[t][j]){
                dis[j]=e[t][j];
            }
        }
        for(int i=1;i<=n-1;i++){ 
            w=(1<<30);
            for(int j=1;j<=n;j++){
                if(dis[j]<w&&dis[j]!=0){
                    w=dis[j];
                    t=j;
                }
            }
            ans+=w;
            dis[t]=0;
            for(int j=1;j<=n;j++){
                if(dis[j]>e[t][j]){
                    dis[j]=e[t][j]; 
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }

    T4:CCT

    最近学校又发了n本五三题霸,BBS看到后十分高兴。但是,当他把五三拿到手后才发现,他已经刷过这些书了!他又认真地看了一会儿,发现新发的这些五三是2017版的,而他刷的是2016版的。现在他想找出所有他没有刷过的题来刷。每本五三都有m道题,并且它的特征(即它和去年版本的五三的差距)可以用一个m位二进制数来代表,二进制位上的1代表该题不同,0代表该题相同。比如4(100)就代表题目3和去年的有不同、5(101)就代表题目1和题目3和去年的有不同。而BBS热衷于给自己找麻烦,他要选择连续一段的几本五三一起刷,并且要求,所有选择的五三的特征中的所有k位中每一位出现1的次数都相同。他又想去刷最多的书,请你告诉他,他最多能刷多少本书?

    输入格式:

    第一行为两个整数 n、m,接下来的n行为 n 个整数,表示每本五三的特征。

    输出格式:

    一个整数,表示BBS最多能刷几本书。

    样例输入

    样例输出

    7 3

    7

    6

    7

    2

    1

    4

    2

    4

    样例解释:

    这7本五三的特征分别为111,110,111,010,001,100,010。选择第3本至第6本五三,这些五三的特征中每一位都出现了2次1。当然,选择第4本到第6本也是可以的,这些五三的特征中每一位都出现了1次1。只是这样子BBS刷的书的数量就少了,他就会不高兴。

    数据范围:

    对于 100%的数据:1<=n<=100000,1<=k<=30。

    solution: 

    对于一个特征a1a2a3...am,我们用(a1-a1)(a2-a1)(a3-a1)...(am-a1)来表示它,然后再做对每一位前缀和(s1-s1)(s2-s1)(s3-s1)...(sm-s1)。易发现,当两个位置i、j前缀和相同时,i+1到j或i到j-1即是一种可行的选法。用个set记住每个前缀和最早出现的位置,对每个位置在set中查询并更新答案即可。(好吧,这是题解,其实我不会用set( ・´ω`・ ))

    #include <cstdio>
    #include <set>
     
    int k;
    struct sth
    {
        int num;
        int dif[30];
        bool operator <(const sth &b)const
        {
            int i;
            for(i=1;i<k;i++)
            {
                if(dif[i]!=b.dif[i]) return dif[i]<b.dif[i];
            }
            return false;
        }
    }t;
    std::set<sth> s;
    std::set<sth>::iterator it;
    int n,x,ans;
    int sum[100001][31];
     
    int max(int a,int b)
    {
        return a>b?a:b;
    }
     
    int main()
    {
        freopen("cct.in","r",stdin);
        freopen("cct.out","w",stdout);
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            for(int j=1;j<=k;j++)
            {
                sum[i][j]=sum[i-1][j];
                if(x&(1<<(j-1))) sum[i][j]++;
            }
        }
        ans=0;
        t.num=0;
        for(int i=1;i<k;i++) t.dif[i]=0;
        s.insert(t);
        for(int i=1;i<=n;i++)
        {
            t.num=i;
            for(int j=1;j<k;j++) t.dif[j]=sum[i][j]-sum[i][j+1];
            it=s.find(t);
            if(it==s.end()) s.insert(t);
            else ans=max(ans,i-(*it).num);
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    PostgreSQL主从流复制部署
    MySQL集群主从复制搭建
    zabbix修改支持中文主机名
    BGP总结(三)
    BGP总结(二)
    BGP总结(一)
    VXLAN配置实例(华为)
    VXLAN理论解析
    飞塔创建IPSec
    关于SANGFOR AC记录上网记录
  • 原文地址:https://www.cnblogs.com/qizhengquan/p/7505999.html
Copyright © 2011-2022 走看看