警示后人,如果你WA#4
查看原帖
警示后人,如果你WA#4
925506
ACRUSHj楼主2023/10/27 21:27

为了方便取前缀 min,我将 min 数组 b0b_0 赋为 10910^9。

然后 #4 正好卡掉了这个东西,我的代码是这样的:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int T,n,m,a[N],b[N],ans;
struct node{int l,r,tag,sum;}t1[N<<2],t2[N<<2];
//1存前缀min,2存分节位置
//1:区间覆盖,单点查询
//2:区间覆盖,区间求和
void up(int u){
    t2[u].sum=t2[u<<1].sum+t2[u<<1|1].sum;
}
void down1(int u){
    if(t1[u].tag<0)return;
    t1[u<<1].tag=t1[u].tag;
    t1[u<<1|1].tag=t1[u].tag;
    t1[u].tag=-1;
}
void down2(int u){
    if(t2[u].tag<0)return;
    t2[u<<1].tag=t2[u].tag;
    t2[u<<1|1].tag=t2[u].tag;
    t2[u<<1].sum=(t2[u<<1].r-t2[u<<1].l+1)*t2[u].tag;
    t2[u<<1|1].sum=(t2[u<<1|1].r-t2[u<<1|1].l+1)*t2[u].tag;
    t2[u].tag=-1;
}
void build1(int u,int L,int R){
    t1[u].l=L;t1[u].r=R;t1[u].tag=-1;
    if(L==R)return;
    int mid=L+R>>1;
    build1(u<<1,L,mid);build1(u<<1|1,mid+1,R);
}
void build2(int u,int L,int R){
    t2[u].l=L;t2[u].r=R;t2[u].tag=-1;t2[u].sum=0;
    if(L==R)return;
    int mid=L+R>>1;
    build2(u<<1,L,mid);build2(u<<1|1,mid+1,R);
}
int query1(int u,int pos){
    if(t1[u].l==t1[u].r)return t1[u].tag;
    int mid=t1[u].l+t1[u].r>>1;
    down1(u);
    if(mid>=pos)return query1(u<<1,pos);
    else return query1(u<<1|1,pos);
}
int query2(int u,int L,int R){
    if(t2[u].l>R||t2[u].r<L)return 0;
    if(t2[u].l>=L&&t2[u].r<=R)return t2[u].sum;
    down2(u);
    return query2(u<<1,L,R)+query2(u<<1|1,L,R);
}
void modify1(int u,int L,int R,int val){
    if(t1[u].r<L||t1[u].l>R)return;
    if(t1[u].l>=L&&t1[u].r<=R)return t1[u].tag=val,void();
    down1(u);
    modify1(u<<1,L,R,val);modify1(u<<1|1,L,R,val);
}
void modify2(int u,int L,int R,int val){
    if(t2[u].r<L||t2[u].l>R)return;
    if(t2[u].l>=L&&t2[u].r<=R)return t2[u].tag=val,t2[u].sum=(t2[u].r-t2[u].l+1)*val,void();
    down2(u);
    modify2(u<<1,L,R,val);modify2(u<<1|1,L,R,val);
    up(u);
}
void solve(){
    scanf("%d%d",&n,&m);ans=0;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=min(b[i-1],a[i]);
    build1(1,1,n);build2(1,1,n);
    for(int i=1;i<=n;i++)if(b[i]!=b[i-1])ans++,modify2(1,i,i,1);
    for(int i=1;i<=n;i++)modify1(1,i,i,b[i]);
    // for(int i=1;i<=n;i++)printf("%d ",query1(1,i));puts("");
    // for(int i=1;i<=n;i++)printf("%d ",query2(1,i,i));puts("");
    while(m--){
        int x,y;
        scanf("%d%d",&x,&y);a[x]-=y;
        if(query1(1,x)<=a[x]){printf("%d ",ans);continue;}
        int L=x+1,R=n,pos=x;
        while(L<=R){
            int mid=L+R>>1;
            if(query1(1,mid)<a[x])R=mid-1;
            else L=mid+1,pos=max(pos,mid);
        }
        if(x+1<=pos)modify2(1,x+1,pos,0);
        modify2(1,x,x,1);
        modify1(1,x,pos,a[x]);
        printf("%d ",ans=query2(1,1,n));
        // for(int i=1;i<=n;i++)printf("%d ",query1(1,i));puts("");
        // for(int i=1;i<=n;i++)printf("%d ",query2(1,i,i));puts("");
    }
    return puts(""),void();
}
signed main(){
    // freopen("temp.in","r",stdin);
    // freopen("CF1690G.out","w",stdout);
    b[0]=1e9;
    scanf("%d",&T);
    while(T--)solve();
    return 0;
}

#4 的 a1a_1 在某个时刻变成了 10910^9,导致答案少了 11。

这个问题害得我调了将近 1h,希望这个帖子能帮到你。

2023/10/27 21:27
加载中...