E. Greedy Shopping

题目链接:https://codeforces.ml/contest/1440/my
题意:两种操作  一种是 1~x 取a[i]=max(v,a[i])  第二种操作是给 y的钱 从x~n 每一道菜 价钱a[i] 能买就买并扣钱 

否则就跳过  查询 每次买了多少道菜
思路:线段树维护   查询的时候要用到区间和 来进行区间查询, 要同时维护最大值和区间和, 那么需要max1 

来去掉当前区间的部分区间,即取当前区间的某符合条件的子区间, 同时也要维护min1来剪枝   

操作1中  是min1>=v 时 整个区间就没必要在查询了,  操作2中是  min1>v时  就没有符合的菜在该区间中了

E. Greedy Shopping
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 #define pb push_back
  5 const int mod=1e9+7;
  6 const int maxn=2e5+10;
  7 struct ac
  8 {
  9     int l,r;
 10     int lazy;
 11     int min1;
 12     int len;
 13     ll max1;
 14     ll sum;
 15 };
 16 ac tree[maxn*4];
 17 
 18 void pushup(int x)
 19 {
 20     tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum;
 21     tree[x].min1=min(tree[x<<1].min1,tree[x<<1|1].min1);
 22     tree[x].max1=max(tree[x<<1].max1,tree[x<<1|1].max1);
 23 }
 24 
 25 void pushdown(int x)
 26 {
 27     ll v=tree[x].lazy;
 28     if(v)
 29     {
 30         tree[x<<1].lazy=tree[x<<1].min1=tree[x<<1].max1=v;
 31         tree[x<<1].sum=v*tree[x<<1].len;
 32         tree[x<<1|1].lazy=tree[x<<1|1].min1=tree[x<<1|1].max1=v;
 33         tree[x<<1|1].sum=v*tree[x<<1|1].len;
 34         tree[x].lazy=0;
 35     }
 36 }
 37 
 38 
 39 
 40 void build(int x,int l,int r)
 41 {
 42     tree[x].l=l,tree[x].r=r;
 43     tree[x].len=r-l+1;
 44     if(l==r)
 45     {
 46         int v;
 47         cin>>v;
 48         tree[x].max1=tree[x].min1=tree[x].sum=v;
 49     }
 50     else
 51     {
 52         int mid=(l+r)/2;
 53         build(x<<1,l,mid);
 54         build(x<<1|1,mid+1,r);
 55         pushup(x);
 56     }
 57 }
 58 
 59 void update(int x,int l,int r,int v)
 60 {
 61     int L=tree[x].l,R=tree[x].r;
 62     if(tree[x].min1>=v)  //要有等号
 63         return;
 64     if(l<=L&&R<=r&&tree[x].max1<v)
 65     {
 66         tree[x].lazy=tree[x].min1=tree[x].max1=v;
 67         tree[x].sum=1ll*v*tree[x].len;
 68     }
 69     else
 70     {
 71         pushdown(x);
 72         int mid=(L+R)/2;
 73         if(l<=mid) update(x<<1,l,r,v);
 74         if(r>mid) update(x<<1|1,l,r,v);
 75         pushup(x);
 76     }
 77 }
 78 
 79 int query(int x,int l,int r,int &v)
 80 {
 81     if(tree[x].min1>v)
 82         return 0;
 83     int L=tree[x].l,R=tree[x].r;
 84     if(l<=L&&R<=r&&tree[x].sum<=v)
 85     {
 86         v-=tree[x].sum;
 87         return tree[x].len;
 88     }
 89     else
 90     {
 91         int mid=(L+R)/2;
 92         pushdown(x);
 93         int ans=0;
 94         if(l<=mid) ans+=query(x<<1,l,r,v);
 95         if(r>mid) ans+=query(x<<1|1,l,r,v);
 96         return ans;
 97     }
 98 }
 99 
100 
101 
102 int main()
103 {
104     ios::sync_with_stdio(0);
105     cin.tie(0);
106     int n,q;
107     cin>>n>>q;
108     build(1,1,n);
109     while(q--)
110     {
111         int t,x,y;
112         cin>>t>>x>>y;
113         if(t==1)
114         {
115             update(1,1,x,y);
116         }
117         else
118         {
119             cout<<query(1,x,n,y)<<'\n';
120         }
121     }
122 
123 
124 
125 }
View Code

 

上一篇:CodeForces 489C


下一篇:LeetCode #628. Maximum Product of Three Numbers