「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了....

原文地址:https://www.cnblogs.com/Wwb123/p/11790405.html