CodeForces 1439 - Problem C - Greedy Shopping - 吉司机线段树
这题实在把我心态搞崩了
WA了一万发
错误答案吧先留着吧,以后补,今天实在没心情补了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e5+50;
struct node{
ll mx;
ll mn;
ll sum;
};
int n,q;
ll arr[N<<2];
ll lazy[N<<2];
node tree[N<<2];
void pushdown(int rt,int l,int r){
if(lazy[rt]){
int mid = l+r>>1;
int ls = rt<<1;
int rs = rt<<1|1;
tree[ls].mx = tree[rs].mx = tree[ls].mn = tree[rs].mn = lazy[rt];
tree[ls].sum = (mid-l+1) * lazy[rt];
tree[rs].sum = (r-mid) * lazy[rt];
lazy[rt] = 0;
}
}
void pushup(int rt){
tree[rt].mx = tree[rt<<1].mx;
tree[rt].mn = tree[rt<<1|1].mn;
tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
}
void build(int l,int r,int rt){
if(l==r){
tree[rt].sum = tree[rt].mx = tree[rt].mn = arr[l];
}else{
build(l,l+r>>1,rt<<1);
build(1+(l+r>>1),r,rt<<1|1);
pushup(rt);
}
}
void update(int l,int r,int rt,int ul,int ur,ll v){
if(ul <= l && ur >= r){
if(tree[rt].mn >= v)return;
else if(tree[rt].mx <= v){
tree[rt].mn=tree[rt].mx=v;
tree[rt].sum=(r-l+1)*v;
lazy[rt]=v;
return;
}else{
int mid=l+r>>1;
pushdown(rt,l,r);
update(l,mid,rt<<1,l,mid,v);
update(mid+1,r,rt<<1|1,mid+1,r,v);
pushup(rt);
}
}else{
int mid=l+r>>1;
pushdown(rt,l,r);
if(ul<=mid){
update(l,mid,rt<<1,ul,ur,v);
}
if(ur>mid){
update(mid+1,r,rt<<1|1,ul,ur,v);
}
pushup(rt);
}
}
ll query_mx(int l,int r,int rt,int pos){ // 区间最大值实际上就在左端点.
if(tree[rt].mx==tree[rt].mn){
return tree[rt].mx;
}else{
pushdown(rt,l,r);
int mid = l+r>>1;
if(pos <= mid)return query_mx(l,mid,rt<<1,pos);
else return query_mx(mid+1,r,rt<<1|1,pos);
}
}
ll query_sum(int l,int r,int rt,int ql,int qr){
if(ql <= l && qr >= r){
return tree[rt].sum;
}else{
pushdown(rt,l,r);
int mid = l+r>>1;
ll ans = 0;
if(ql <= mid)ans += query_sum(l,mid,rt<<1,ql,qr);
if(qr > mid) ans += query_sum(mid+1,r,rt<<1|1,ql,qr);
return ans;
}
}
pii getans(int x,ll v){
int l = x,r = n;
int bg = -1,ed = -1;
while(l <= r){
int mid = l+r>>1;
if(query_mx(1,n,1,mid) <= v){
bg = mid;
r = mid-1;
}else{
l = mid+1;
}
}
if(bg==-1)return make_pair(-1,-1);
l = bg;
r = n;
while(l <= r){
int mid = l+r>>1;
if(query_sum(1,n,1,bg,mid) <= v){
ed = mid;
l = mid+1;
}else{
r = mid-1;
}
}
return make_pair(bg,ed);
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){scanf("%lld",&arr[i]);}
build(1,n,1);
int x,y; ll z;
while(q--){
scanf("%d%d%lld",&x,&y,&z);
if(x==1){
update(1,n,1,1,y,z);
}else{
int ans = 0;
while(1){
pii g = getans(y,z);
if(g.first==-1)break;
ans += g.second-g.first+1;
y=g.second+1;
z-=query_sum(1,n,1,g.first,g.second);
if(y>n)break;
}
printf("%d\n",ans);
}
}
// system("pause");
return 0;
}
update 2020.11.18
刚刚听说这题貌似要用到吉如一线段树,维护最大值和次大值.
但是为什么我这个代码会wa呢?
即便复杂度不够优秀也不应该wa啊.
等我学完吉如一线段树再回来看看吧.
---- suffer now and live the rest of your life as a champion ----