只过了hack,玄关求调

P2572 [SCOI2010] 序列操作

dami826 @ 2024-08-07 16:31:53

#include<bits/stdc++.h>
using namespace std;
int n,m,s[100001];
struct segment_tree{
    int one[400001],len[400001][2],llen[400001][2],rlen[400001][2],cover[400001],reverse[400001],tmp[400001][3];//cover:0不须覆盖,1覆盖0,2覆盖1 
    void up(int left,int right,int index,int mid){
        one[index]=one[index*2]+one[index*2+1];
//      printf("one %d comes to %d 1\n",index,one[index]);
//      printf("one %d(%d)+one %d(%d)=one %d\n",index*2,one[index*2],index*2+1,one[index*2+1],index);
        for(int i=0;i<=1;i++){
            len[index][i]=max(max(len[index*2][i],len[index*2+1][i]),rlen[index*2][i]+llen[index*2+1][i]);
            llen[index][i]=(llen[index*2][i]==mid-left+1)?(llen[index*2][i]+llen[index*2+1][i]):(llen[index*2][i]);
            rlen[index][i]=(rlen[index*2+1][i]==right-mid)?(rlen[index*2][i]+rlen[index*2+1][i]):(rlen[index*2+1][i]);
        }
    }
    void build(int left,int right,int index){
        if(left==right){
            one[index]=s[left];
//          printf("one %d comes to %d 2\n",index,one[index]);
            len[index][s[left]]=llen[index][s[left]]=rlen[index][s[left]]=1;
            return;
        }
        int mid=(left+right)/2;
        build(left,mid,index*2);
        build(mid+1,right,index*2+1);
        up(left,right,index,mid);
    }
    void down(int left,int right,int index,int mid){
        if(cover[index]){
            cover[index*2]=cover[index*2+1]=cover[index];
            reverse[index*2]=reverse[index*2+1]=0;
            one[index*2]=(cover[index]-1)?(mid-left+1):0;
            one[index*2+1]=(cover[index]-1)?(right-mid):0;
//          printf("one %d comes to %d 3\n",index*2,one[index*2]);
//          printf("one %d comes to %d 4\n",index*2+1,one[index*2+1]);
            len[index*2][cover[index]^1]=llen[index*2][cover[index]-1]=rlen[index*2][cover[index-1]]=mid-left+1;
            len[index*2][(cover[index]-1)^1]=llen[index*2][(cover[index]-1)^1]=rlen[index*2][(cover[index]-1)^1]=0;
            len[index*2+1][cover[index]-1]=llen[index*2+1][cover[index]-1]=rlen[index*2+1][cover[index-1]]=right-mid;
            len[index*2+1][(cover[index]-1)^1]=llen[index*2+1][(cover[index]-1)^1]=rlen[index*2+1][(cover[index]-1)^1]=0;
            reverse[index]=cover[index]=0;
        }
        if(reverse[index]){
            one[index*2]=(mid-left+1)-one[index*2];
            one[index*2+1]=(right-mid)-one[index*2+1];
//          printf("one %d comes to %d 5\n",index*2,one[index*2]);
//          printf("one %d comes to %d 6\n",index*2+1,one[index*2+1]);
            if(cover[index*2]){
                (cover[index*2]-1)?cover[index*2]--:cover[index*2]++;
            }
            else{
                reverse[index*2]^=1;
            }
            if(cover[index*2+1]){
                (cover[index*2+1]-1)?cover[index*2+1]--:cover[index*2+1]++;
            }
            else{
                reverse[index*2+1]^=1;
            }
            swap(len[index][0],len[index][1]);
            swap(llen[index][0],llen[index][1]);
            swap(rlen[index][0],rlen[index][1]);
            reverse[index]=0;
        }
    } 
    void c_update(int gleft,int gright,int x,int left,int right,int index){//cover_update 
        //printf("c %d %d %d %d %d %d\n",gleft,gright,x,left,right,index);
        if(right<gleft||gright<left){
            return;
        }
        if(gleft<=left&&right<=gright){
            cover[index]=x+1;
            one[index]=x?(right-left+1):0;
//          printf("one %d comes to %d 7\n",index,one[index]);
            len[index][x]=llen[index][x]=rlen[index][x]=right-left+1;
            len[index][x^1]=llen[index][x^1]=rlen[index][x^1]=0;
            return;
        }
        int mid=(left+right)/2;
        down(left,right,index,mid);
        c_update(gleft,gright,x,left,mid,index*2);
        c_update(gleft,gright,x,mid+1,right,index*2+1);
        up(left,right,index,mid);
    }
    void r_update(int gleft,int gright,int left,int right,int index){
//      printf("r %d %d %d %d %d\n",gleft,gright,left,right,index);
        if(right<gleft||gright<left){
            return;
        }
        if(gleft<=left&&right<=gright){
            if(cover[index]){
                (cover[index]-1)?cover[index]--:cover[index]++;
            }
            else{
                reverse[index]^=1;
            }
            one[index]=(right-left+1)-one[index];
//          printf("one %d comes to %d 8\n",index,one[index]);
            swap(len[index][0],len[index][1]);
            swap(llen[index][0],llen[index][1]);
            swap(rlen[index][0],rlen[index][1]);
            return;
        }
        int mid=(left+right)/2;
        down(left,right,index,mid);
        r_update(gleft,gright,left,mid,index*2);
        r_update(gleft,gright,mid+1,right,index*2+1);
        up(left,right,index,mid);
    }
    int one_search(int gleft,int gright,int left,int right,int index){
//      printf("%d %d %d %d %d\n",gleft,gright,left,right,index);
        if(right<gleft||gright<left){
//          printf("Nope\n");
            return 0;
        }
        if(gleft<=left&&right<=gright){
//          printf("OK return %d\n",one[index]);
            return one[index];
        }
//      printf("continue\n");
        int mid=(left+right)/2;
        down(left,right,index,mid);
        return one_search(gleft,gright,left,mid,index*2)+one_search(gleft,gright,mid+1,right,index*2+1);
    }
    int* len_search(int gleft,int gright,int left,int right,int index){
//      printf("%d %d %d %d %d\n",gleft,gright,left,right,index);
        if(right<gleft||gright<left){
//          printf("Nope\n");
            tmp[index][0]=tmp[index][1]=tmp[index][2]=0;
            return &tmp[index][0];
        }
        if(gleft<=left&&right<=gright){
            tmp[index][0]=len[index][1];
            tmp[index][1]=llen[index][1];
            tmp[index][2]=rlen[index][1];
//          printf("OK return %d %d\n",tmp[0],&tmp[0]);
            return &tmp[index][0];
        }
//      printf("continue\n");
        int mid=(left+right)/2;
        down(left,right,index,mid);
        int *a=len_search(gleft,gright,left,mid,index*2),*b=len_search(gleft,gright,mid+1,right,index*2+1);
        tmp[index][1]=(*(a+1)==mid-left+1)?(*(a+1)+*(b+1)):*(a+1);
        tmp[index][2]=(*(b+2)==right-mid)?(*(b+2)+*(a+2)):*(b+2);
        tmp[index][0]=max(max(*a,*b),*(a+2)+*(b+1));
//      printf("%d\n",*a);
        return &tmp[index][0];
    }
}; 
segment_tree tr;
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&s[i]);
    }
    tr.build(1,n,1);
    while(m--){
        int op,l,r;
        scanf("%d %d %d",&op,&l,&r);
        l++;
        r++;
        switch(op){
            case 0:case 1:tr.c_update(l,r,op,1,n,1);break;
            case 2:tr.r_update(l,r,1,n,1);break;
            case 3:printf("%d\n",tr.one_search(l,r,1,n,1));break;
            case 4:
                int *x=tr.len_search(l,r,1,n,1);
                printf("%d\n",*x);
        }
    }
    return 0; 
}

by dami826 @ 2024-08-08 10:19:57

down函数中的swap

swap(len[index][0],len[index][1]);
swap(llen[index][0],llen[index][1]);
swap(rlen[index][0],rlen[index][1]);

换成

swap(len[index*2][0],len[index*2][1]);
swap(llen[index*2][0],llen[index*2][1]);
swap(rlen[index*2][0],rlen[index*2][1]);
swap(len[index*2+1][0],len[index*2+1][1]);
swap(llen[index*2+1][0],llen[index*2+1][1]);
swap(rlen[index*2+1][0],rlen[index*2+1][1]);

之后已AC,此贴结


by Night_early @ 2024-08-08 10:24:58

@dami826 问一下为什么


by dami826 @ 2024-08-08 10:31:56

@Night_early pushdown更新的应该是子节点的信息,父节点的信息在标懒标记的时候已经更新过了 我也不知道为什么这么离谱的错误居然能过样例和#11


by Night_early @ 2024-08-08 10:58:59

@dami826 确实,您有兴趣调我的吗https://www.luogu.com.cn/record/171322560


|