• 「11.03」 陶陶摘苹果(线段树)开心的金明(贪心)笨小猴(乱搞)


    又考了一场试,昨天放假稍蒙比...,距离csps还有十天,希望比以前的自己更用心

    A. 陶陶摘苹果


    做法有很多,联想起以前考过的一个单调栈、倍增的题,然而我直接用的无脑线段树做法。

    倒序建树离线储存答案,每次因为在修改点之前的决策不受影响,所以可以预处理前面的影响

    后面的影响其实就是一个单调栈嘛.......

    %%%%%%zzn,xkl用分块在线跑过

    可以线段树维护单调栈,虽然两个log

    #include<bits/stdc++.h>
    #define MAXN 2100000
    #define inf 0x7ffffffffffff
    using namespace std;
    int read(){
        char c=getchar();int x=0;int ff=1;
        while(c<'0'||c>'9'){if(c=='-')ff=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return x*ff;
    }
    int m;struct node{int l,r,sum,w;}t[MAXN];int n,a[MAXN];
    int cal(int k,int w){
        if(t[k].l==t[k].r)return t[k].sum>w;
        if(t[k*2].sum>w)return cal(k*2,w)+t[k*2+1].w;
        else return cal(k*2+1,w);
    }
    void updata(int k){
        t[k].sum=max(t[k*2].sum,t[k*2+1].sum);
        t[k*2+1].w=cal(k*2+1,t[k*2].sum);
    }
    void build(int k,int l,int r){
        t[k].l=l;t[k].r=r;
        if(l==r){t[k].sum=a[l];return ;}
        int mid=(t[k].l+t[k].r)>>1;
        build(k*2,l,mid);
        build(k*2+1,mid+1,r);
        updata(k);
    }
    void add(int k,int x){
        if(t[k].l==t[k].r){t[k].sum=a[t[k].l];return ;}
        int mid=(t[k].l+t[k].r)>>1;
        if(x<=mid)add(k*2,x);
        else add(k*2+1,x);
        updata(k);
    }
    signed main(){
        freopen("TaoPApp.in","r",stdin);
        freopen("TaoPApp.out","w",stdout);
        n=read();m=read();
        for(int i=1;i<=n;++i)a[i]=read();
        build(1,1,n);
        for(int i=1;i<=m;++i){
            int pos=read();int h=read();int y=a[pos];
            a[pos]=h;
            add(1,pos);
            printf("%d
    ",cal(1,-1));
            a[pos]=y;
            add(1,pos);
        }
    }
    View Code

    B. 开心的金明


    一道很大神的贪心题。。。。。。

    题面是在考我的语文阅读能力QAQ

    首先对于原材料而言,他的成本对每个月而言都是可以提前算出来的

    然后对于电脑而言一个时有储存的限制,一个是有生产的限制

    考场上打的是$n*e_{i}$的DP,但是$e$的范围是$1e8$,当场去世,想写贪心却没有思路

    首先需要知道一个性质,对于当前销售,销售成本更低的商品提前销售更优

    因为在不考虑储存限制的情况小,当前商品$->$下一个月都是加了一个$E_{i}$的值,也就是说他们的优先程度还是不变的

    当我们现在选择最优的一定不会是结果更差

    然后我们每次都将全部生产,在以后的转移中如果发现可储存的值比较小,就舍弃掉成本最大的计算机,可以用一个堆来实现

    至于$WA80$(也可能$WA10$)是因为可能存在当前的计算机总数小于当前的$e_{i}$数量

    注意细节

     1 #include<bits/stdc++.h>
     2 #define MAXN 2100000
     3 #define inf 0x7ffffffffffff
     4 #define int long long
     5 using namespace std;
     6 int read(){
     7     char c=getchar();int x=0;int ff=1;
     8     while(c<'0'||c>'9'){if(c=='-')ff=-1;c=getchar();}
     9     while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    10     return x*ff;
    11 }
    12 int c[MAXN];//原材料费用
    13 int d[MAXN];//需求
    14 int p[MAXN];//生产量
    15 int m[MAXN];//电脑价钱
    16 int e[MAXN];//电脑储存数
    17 int R[MAXN];//原材料储存价钱
    18 int E[MAXN];//电脑储存价钱
    19 int n;
    20 int noww[MAXN];int ok;
    21 struct node{
    22     int val,sum,id;
    23     friend bool operator <(node a,node b){
    24         return a.val>b.val;
    25     }
    26 }kx[MAXN];
    27 priority_queue<node>q;
    28 bool cmp(node a,node b){
    29     return a.val>b.val;
    30 }
    31 int sum[MAXN];
    32 int ans=0;
    33 signed main(){
    34     freopen("happy.in","r",stdin);
    35     freopen("happy.out","w",stdout);
    36     n=read();
    37     for(int i=1;i<=n;++i){
    38         c[i]=read();d[i]=read();m[i]=read();p[i]=read();
    39     }
    40     for(int i=1;i<=n-1;++i){
    41         e[i]=read();R[i]=read();E[i]=read();
    42     }
    43     noww[1]=c[1];
    44     for(int i=2;i<=n;++i){
    45         noww[i]=min(noww[i-1]+R[i-1],c[i]);
    46     }
    47     for(int i=1;i<=n;++i){
    48         q.push((node){noww[i]+m[i],p[i],i});
    49         sum[i]=p[i];
    50         ans+=(noww[i]+m[i])*p[i];
    51         int ned=d[i];int tot=0;int tsum=0;
    52         while(!q.empty()){
    53             node x=q.top();q.pop();
    54             if(ned>=x.sum){
    55                 ned-=x.sum;
    56                 sum[x.id]-=x.sum;
    57             }
    58             else{
    59                 sum[x.id]-=ned;ned=0;
    60             }
    61             if(sum[x.id]!=0){
    62                 kx[++tot].id=x.id;
    63                 kx[tot].sum=sum[x.id];
    64                 kx[tot].val=x.val;
    65                 tsum+=sum[x.id];
    66             }
    67         }
    68         if(ned!=0){ok=1;break;}
    69         sort(kx+1,kx+tot+1,cmp);
    70         for(int j=1;j<=tot;++j){
    71             if(tsum<=e[i])break;
    72             if(tsum-e[i]>=sum[kx[j].id]){
    73                 ans-=kx[j].val*sum[kx[j].id];
    74                 tsum-=sum[kx[j].id];
    75                 sum[kx[j].id]=0;
    76             }
    77             else {
    78                 ans-=kx[j].val*(tsum-e[i]);
    79                 sum[kx[j].id]-=tsum-e[i];
    80                 tsum=e[i];
    81             }
    82         }
    83         for(int j=1;j<=tot;++j){
    84             if(sum[kx[j].id]==0)continue;
    85             q.push((node){kx[j].val+E[i],sum[kx[j].id],kx[j].id});
    86         }
    87         ans+=tsum*E[i];
    88     }
    89     if(ok==1)printf("-1");
    90     else printf("%lld
    ",ans);
    91 }
    View Code

     思路积累:

    1.贪心思考,可以先加后来根据决策再减,类似反悔的过程

    2.别死刚DP....

    C. 笨小猴


    由于某些sb理由考场随机化没有AC,注意结构体的下标与原下标的关系

    然后可以瞎rand了....

  • 相关阅读:
    java jni 调用c语言函数
    BeautifulSoup入门
    Python单引号、双引号、三个双引号的区别
    Request库的安装与使用
    awk命令入门
    sed命令入门
    编译生成protobuf的jar包
    编辑crontab添加Linux计划任务
    tar命令详解及使用实例
    MySQL用户管理
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11790405.html
Copyright © 2020-2023  润新知