• 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范围内

  • 相关阅读:
    django页面分类和继承
    django前端从数据库获取请求参数
    pycharm配置django工程
    django 应用各个py文件代码
    CF. 1428G2. Lucky Numbers(背包DP 二进制优化 贪心)
    HDU. 6566. The Hanged Man(树形背包DP DFS序 重链剖分)
    小米邀请赛 决赛. B. Rikka with Maximum Segment Sum(分治 决策单调性)
    区间树 学习笔记
    CF GYM. 102861M. Machine Gun(主席树)
    2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016) (B, D, G, H)
  • 原文地址:https://www.cnblogs.com/thmyl/p/7483248.html
Copyright © 2020-2023  润新知