zoukankan      html  css  js  c++  java
  • 2014-10-6 NOIP模拟赛

    1. 锻炼计划(exercise.pas)

    身体是革命的本钱,OIers不要因为紧张的学习和整天在电脑前而忽视了健康问题。小x设计了自己的锻炼计划,但他不知道这个计划是否可行,换句话说如果计划不当可能会让他的体力超支,所以小x请你帮助他。

    一天有1440分钟,所以小x列出的是这一整天第1至第1440分钟的计划。小x的体力用一个整数来表示,他会按照计划表进行锻炼,同时,每分钟小x的体力会自动增加1。如果某一分钟末小x的体力小于等于零,那么可怜的小x就累死了……

    输入(exercise.in)

    第一行是用空格分开的两个整数n,m,分别表示小x的初始体力值和计划的项目数量。

    从第二行开始的m行,每行描述一个锻炼项目:名称、开始时间a、结束时间b、每分钟耗费的体力(用空格分隔),表示此项目从第a分钟初开始,第b分钟末结束。锻炼项目按照开始时间递增顺序给出,不会出现两个项目时间冲突的情况。

    输出(exercise.out)

           输出包括两行,如果计划可行,第一行输出"Accepted",第二行输出这一天过后最后剩余的体力;否则在第一行输出"Runtime Error",第二行输出在第几分钟累死。

    样例

    Input

    Output

    10 1

    Basketball 1 10 1

    Accepted

    1440

    1 1

    Nunchakus 1 1 2

    Runtime Error

    1

    约定

    0<n<=2^31-1

    0<=m<=500

    所有中间值的绝对值不会超过2^31-1

    每一个锻炼项目的名称不超过20个字符,其中不含空格。

    /*
        线段树维护每分钟消耗的体力,每个运动相当于一个区间查询
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define maxn 510
    long long s,a[2000],b[2000];
    int n;
    char ch[30];
    struct node{
        int l,r;
        long long v,lazy;
    }tr[maxn<<4];
    long long qread(){
        long long i=0;
        char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();}
        return i;
    }
    void build(int l,int r,int k){
        tr[k].l=l;tr[k].r=r;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(l,mid,k<<1);
        build(mid+1,r,k<<1|1);
    }
    void updata(int k){
        if(tr[k].l==tr[k].r)return;
        int l,r;
        long long v=tr[k].lazy;
        l=tr[k<<1].l;r=tr[k<<1].r;
        tr[k<<1].v=(r-l+1)*v;
        tr[k<<1].lazy+=v;
        
        l=tr[k<<1|1].l,r=tr[k<<1|1].r;
        tr[k<<1|1].v=(r-l+1)*v;
        tr[k<<1|1].lazy+=v;
        tr[k].lazy=0;
    }
    void change(int l,int r,long long v,int k){
        if(tr[k].l>=l&&tr[k].r<=r){
            tr[k].v+=(tr[k].r-tr[k].l+1)*v;
            tr[k].lazy+=v;
            return;
        }
        if(tr[k].lazy)updata(k);
        int mid=(tr[k].l+tr[k].r)>>1;
        if(l<=mid)change(l,r,v,k<<1);
        if(r>mid)change(l,r,v,k<<1|1);
        tr[k].v=tr[k<<1].v+tr[k<<1|1].v;
    }
    long long find(int op,int k){
        if(tr[k].l==tr[k].r)return tr[k].v;
        if(tr[k].lazy)updata(k);
        int mid=(tr[k].l+tr[k].r)>>1;
        if(op<=mid)return find(op,k<<1);
        if(op>mid)return find(op,k<<1|1);
        tr[k].v=tr[k<<1].v+tr[k<<1|1].v;
    }
    int main(){
        //freopen("Cola.txt","r",stdin);
        freopen("exercise.in","r",stdin);
        freopen("exercise.out","w",stdout);
        s=qread();
        scanf("%d",&n);
        int x,y;long long z;
        build(1,1440,1);
        for(int i=1;i<=n;i++){
            scanf("%s%d%d",ch,&x,&y);
            cin>>z;
            change(x,y,z,1);
        }
        for(int i=1;i<=1440;i++)a[i]=find(i,1);
        b[0]=s;
        for(int i=1;i<=1440;i++){
            b[i]=b[i-1]+1;
            b[i]-=a[i];
            if(b[i]<=0){
                printf("Runtime Error
    %d",i);
                return 0;
            }
        }
        printf("Accepted
    %d",b[1440]);
        return 0;
    }
    100分 线段树

    2.小猫爬山(catclimb.pas)

    题目描述

    Freda和rainbow饲养了N只小猫,这天,小猫们要去爬山。经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。

    Freda和rainbow只好花钱让它们坐索道下山。索道上的缆车最大承重量为W,而N只小猫的重量分别是C1、C2……CN。当然,每辆缆车上的小猫的重量之和不能超过W。每租用一辆缆车,Freda和rainbow就要付1美元,所以他们想知道,最少需要付多少美元才能把这N只小猫都运送下山?

    输入格式

    第一行包含两个用空格隔开的整数,N和W。

    接下来N行每行一个整数,其中第i+1行的整数表示第i只小猫的重量C i。

    输出格式

    输出一个整数,最少需要多少美元,也就是最少需要多少辆缆车。

    样例输入

    5 1996

    1

    2

    1994

    12

    29

    样例输出

    2

    数据范围与约定

    对于100%的数据,1<=N<=18,1<=C i <=W<=10^8。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,w,ans,a[20],b[20];
    void dfs(int now,int sum){
        if(sum>=ans)return;
        if(now==n+1){
            ans=min(ans,sum);
            return;
        }
        for(int i=1;i<=sum;i++){//往以前用过的背包里装 
            if(b[i]+a[now]<=w){
                b[i]+=a[now];
                dfs(now+1,sum);
                b[i]-=a[now];
            }
        }
        if(sum==n)return;
        b[sum+1]+=a[now];
        dfs(now+1,sum+1);
        b[sum+1]-=a[now];
    }
    int main(){
        //freopen("Cola.txt","r",stdin);
        freopen("catclimb.in","r",stdin);
        freopen("catclimb.out","w",stdout);
        scanf("%d%d",&n,&w);ans=n;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        dfs(1,0);
        printf("%d",ans);
        return 0;
    }
    74分 暴力
    /*
        暴力之前先从大到小排个序
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,w,ans,a[20],b[20];
    void dfs(int now,int sum){
        if(sum>=ans)return;
        if(now==n+1){
            ans=min(ans,sum);
            return;
        }
        for(int i=1;i<=sum;i++){//往以前用过的背包里装 
            if(b[i]+a[now]<=w){
                b[i]+=a[now];
                dfs(now+1,sum);
                b[i]-=a[now];
            }
        }
        if(sum==n)return;
        b[sum+1]+=a[now];
        dfs(now+1,sum+1);
        b[sum+1]-=a[now];
    }
    bool cmp(int x,int y){
        return x>y;
    }
    int main(){
        //freopen("Cola.txt","r",stdin);
        freopen("catclimb.in","r",stdin);
        freopen("catclimb.out","w",stdout);
        scanf("%d%d",&n,&w);ans=n;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        sort(a+1,a+n+1,cmp);
        dfs(1,0);
        printf("%d",ans);
        return 0;
    }
    100分

    3.魔兽争霸(war.pas)

    小x正在销魂地玩魔兽

    他正控制着死亡骑士和n个食尸鬼(编号1~n)去打猎

    死亡骑士有个魔法,叫做“死亡缠绕”,可以给食尸鬼补充HP

    战斗过程中敌人会对食尸鬼实施攻击,食尸鬼的HP会减少

    小x希望随时知道自己部队的情况,即HP值第k多的食尸鬼有多少HP,以便决定如何施放魔法

    请同学们帮助他:)

    小x向你发出3种信号:(下划线在输入数据中表现为空格)

    A_i_a表示敌军向第i个食尸鬼发出了攻击,并使第i个食尸鬼损失了a点HP,如果它的HP<=0,那么这个食尸鬼就死了(Undead也是要死的……)。

    敌军不会攻击一个已死的食尸鬼。

    C_i_a 表示死亡骑士向第i个食尸鬼放出了死亡缠绕,并使其增加了a点HP。

    HP值没有上限。

    死亡骑士不会向一个已死的食尸鬼发出死亡缠绕

    Q_k  表示小x向你发出询问

    输入(war.in)

    第一行,一个正整数 n

    以后n个整数 表示n个食尸鬼的初始HP值

    接着一个正整数m

    以下m行 每行一个小x发出的信号

    输出(war.out)

    对于小x的每个询问,输出HP第k多的食尸鬼有多少HP,如果食尸鬼总数不足k个,输出-1。每个一行数。

    最后一行输出一个数:战斗结束后剩余的食尸鬼数

    样例

    Input

    Output

    5

    1 2 3

    4 5

    10

    Q 2

    A 4 6

    C 1 4

    Q 2

    A 2 1

    A 3 3

    A 1 3

    Q 4

    C 2 10

    Q 1

    4

    5

    -1

    11

    3

     

    约定

    40%的数据  n<=3000  m<=5000

    70%的数据  n<=8000  m<=10000

    100%的数据  n<=30000  m<=50000

    90%的数据随机生成

    食尸鬼HP没有上限

    数据保证任意时刻食尸鬼的HP值在longint范围内

    数据保证A和C命令中的食尸鬼是活着的

    输入数据中没有多余空格、换行

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,cnt;
    struct node{
        int v,id;
    }a[30010];
    char ch[2];
    bool cmp1(node x,node y){return x.v>y.v;}
    bool cmp2(node x,node y){return x.id<y.id;}
    int main(){
        //freopen("in.txt","r",stdin);
        freopen("war.in","r",stdin);
        freopen("war.out","w",stdout);
        scanf("%d",&n);cnt=n;
        for(int i=1;i<=n;i++)scanf("%d",&a[i].v),a[i].id=i;
        int x,y;
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%s",ch);
            if(ch[0]=='A'){
                scanf("%d%d",&x,&y);
                if(a[x].v<=0)continue;
                a[x].v-=y;
                if(a[x].v<=0)cnt--;
            }
            if(ch[0]=='C'){
                scanf("%d%d",&x,&y);
                if(a[x].v<=0)continue;
                a[x].v+=y;
            }
            if(ch[0]=='Q'){
                scanf("%d",&x);
                if(x>cnt){
                    printf("-1
    ");
                    continue;
                }
                sort(a+1,a+n+1,cmp1);
                printf("%d
    ",a[x].v);
                sort(a+1,a+n+1,cmp2);
            }
        }
        printf("%d
    ",cnt);
        return 0;
    }
    30分 暴力
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<map>
    #include<algorithm>
    #define ll long long 
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int tmp;
    int n,m,root,size;
    int b[300005],v[300005],w[300005],s[300005],rnd[300005];
    int ls[300005],rs[300005];
    bool tag[300005];
    void update(int k){s[k]=s[ls[k]]+s[rs[k]]+w[k];}
    void rturn(int &k)
    {int t=ls[k];ls[k]=rs[t];rs[t]=k;update(k);update(t);k=t;}
    void lturn(int &k)
    {int t=rs[k];rs[k]=ls[t];ls[t]=k;update(k);update(t);k=t;}
    void insert(int &k,int num)
    {
        if(!k){k=++size;rnd[k]=rand();w[k]=s[k]=1;v[k]=num;return;}
        s[k]++;
        if(num==v[k]){w[k]++;return;}
        else if(num<v[k]){insert(ls[k],num);if(rnd[ls[k]]<rnd[k])rturn(k);}
        else {insert(rs[k],num);if(rnd[rs[k]]<rnd[k])lturn(k);}
    }
    void del(int &k,int num)
    {
        if(!k)return;
        if(num==v[k])
        {
            if(w[k]>1){w[k]--;s[k]--;return;}
            if(ls[k]*rs[k]==0)k=ls[k]+rs[k];
            else if(rnd[ls[k]]<rnd[rs[k]]){rturn(k);del(k,num);}
            else {lturn(k);del(k,num);}
        }
        else if(num<v[k])
            {del(ls[k],num);s[k]--;}
        else {del(rs[k],num);s[k]--;}
    }
    int query(int k,int x)
    {
        if(!k)return -1;
        if(s[ls[k]]>=x)return query(ls[k],x);
        else if(x>s[ls[k]]+w[k])return query(rs[k],x-w[k]-s[ls[k]]);
        else return k;
    }
    int main()
    {
        freopen("war.in","r",stdin);
        freopen("war.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++)b[i]=read();
        for(int i=1;i<=n;i++)insert(root,b[i]);
        m=read();
        int k,x;
        for(int i=1;i<=m;i++)
        {
            char ch[2];
            scanf("%s",ch);
            if(ch[0]=='A')
            {
                k=read();x=read();
                del(root,b[k]);b[k]-=x;
                if(b[k]>0)insert(root,b[k]);
                else n--;
            }
            else if(ch[0]=='C')
            {
                k=read();x=read();
                del(root,b[k]);b[k]+=x;
                insert(root,b[k]);
            }
            else 
            {
                k=read();
                if(k>n)puts("-1");
                else printf("%d
    ",v[query(root,n-k+1)]);
            }
        }
        printf("%d
    ",n);
        return 0;
    }
    100分 主席树

    4.暗黑破坏神(diablo.pas)

    无聊中的小x玩起了Diablo I...

    游戏的主人公有n个魔法

    每个魔法分为若干个等级,第i个魔法有p[i]个等级(不包括0)

    每个魔法的每个等级都有一个效果值,一个j级的i种魔法的效果值为w[i][j]

    魔法升一级需要一本相应的魔法书

    购买魔法书需要金币,第i个魔法的魔法书价格为c[i]

    而小x只有m个金币(好孩子不用修改器)

    你的任务就是帮助小x决定如何购买魔法书才能使所有魔法的效果值之和最大

    开始时所有魔法为0级 效果值为0

    输入(diablo.in)

    第一行 用空格隔开的两个整数n m

    以下n行 描述n个魔法

    第i+1行描述 第i个魔法 格式如下

    c[i] p[i] w[i][1] w[i][2] ... w[i][p[i]]

    输出(diablo.out)

    第一行输出一个整数,即最大效果值。

    以后n行输出你的方案:

    第i+1行有一个整数v[i] 表示你决定把第i个魔法学到v[i]级

    如果有多解 输出花费金币最少的一组

    如果还多解 输出任意一组

    样例

    Input

    Output

    3 10

    1 3 1 2 2

    2 3 2 4 6

    3 3 2 1 10

    11

    1

    0

    3

     

    约定

    0<n<=100

    0<m<=500

    0<p[i]<=50

    0<c[i]<=10

    保证输入数据和最终结果在longint范围内

  • 相关阅读:
    hh
    SDUT 3923 打字
    最短路
    阶乘后面0的个数(51Nod 1003)
    大数加法
    Biorhythms(中国剩余定理)
    usaco-5.1-theme-passed
    usaco-5.1-starry-passed
    usaco-5.1-fc-passed
    usaco-4.4-frameup-passed
  • 原文地址:https://www.cnblogs.com/thmyl/p/7483248.html
Copyright © 2011-2022 走看看