• bzoj 4592(洛谷 4344) [Shoi2015]脑洞治疗仪——线段树上二分


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4592

    1操作就是用线段树来二分找到第一个有 k 个0的位置。

    在洛谷上A了,与暴力和网上题解对拍也都没问题。在bzoj上4msWA。不知道为什么。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ls Ls[cr]
    #define rs Rs[cr]
    using namespace std;
    const int N=2e5+5,M=N<<1;
    int n,m,sm[M],fl[M],fr[M],mx[M],Ls[M],Rs[M],lz[M],tot;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    void build(int l,int r,int cr)
    {
      sm[cr]=r-l+1; lz[cr]=-1; if(l==r)return;
      int mid=l+r>>1;
      ls=++tot; build(l,mid,ls);
      rs=++tot; build(mid+1,r,rs);
    }
    void pshd(int cr,int l,int mid,int r)
    {
      if(lz[cr]==-1)return;
      fl[ls]=fr[ls]=mx[ls]=(lz[cr]?0:mid-l+1); sm[ls]=(lz[cr]?mid-l+1:0);
      fl[rs]=fr[rs]=mx[rs]=(lz[cr]?0:r-mid); sm[rs]=(lz[cr]?r-mid:0);
      lz[ls]=lz[rs]=lz[cr]; lz[cr]=-1;
    }
    void pshp(int cr)
    {
      sm[cr]=sm[ls]+sm[rs];
      fl[cr]=fl[ls]+(sm[ls]?0:fl[rs]);
      fr[cr]=fr[rs]+(sm[rs]?0:fr[ls]);
      mx[cr]=max(max(fl[cr],fr[cr]),max(mx[ls],mx[rs]));
      mx[cr]=max(mx[cr],fr[ls]+fl[rs]);
    }
    void mdfy(int l,int r,int cr,int L,int R,bool k)
    {
      if(l>=L&&r<=R)
        {
          fl[cr]=fr[cr]=mx[cr]=(k?0:r-l+1); sm[cr]=(k?r-l+1:0);
          lz[cr]=k; return;
        }
      int mid=l+r>>1; pshd(cr,l,mid,r);
      if(L<=mid)mdfy(l,mid,ls,L,R,k);
      if(mid<R)mdfy(mid+1,r,rs,L,R,k);
      pshp(cr);
    }
    int qry(int l,int r,int cr,int L,int R)
    {
      if(l>=L&&r<=R) return sm[cr];
      int mid=l+r>>1,ret=0; pshd(cr,l,mid,r);
      if(L<=mid) ret=qry(l,mid,ls,L,R);
      if(mid<R) ret+=qry(mid+1,r,rs,L,R);
      return ret;
    }
    int fnd(int l,int r,int cr,int L,int R,int k)
    {
      if(l==r)return l;
      int mid=l+r>>1; pshd(cr,l,mid,r);
      if(l>=L&&r<=R)
        {
          int siz=mid-l+1-sm[ls];
          if(siz>=k)return fnd(l,mid,ls,L,R,k);
          return fnd(mid+1,r,rs,L,R,k-siz);
        }
      if(mid<L)return fnd(mid+1,r,rs,L,R,k);
      if(R<=mid)return fnd(l,mid,ls,L,R,k);
      int d=qry(l,mid,ls,L,R);
      d=mid-max(l,L)+1-d;//L!!!!//max!!!!!probably just r>R
      if(d>=k) return fnd(l,mid,ls,L,R,k);
      return fnd(mid+1,r,rs,L,R,k-d);
    }
    int query(int l,int r,int cr,int L,int R)
    {
      if(l>=L&&r<=R)return mx[cr];
      int mid=l+r>>1; pshd(cr,l,mid,r);
      if(mid<L) return query(mid+1,r,rs,L,R);
      if(R<=mid) return query(l,mid,ls,L,R);
      int ret=max(query(l,mid,ls,L,R),query(mid+1,r,rs,L,R));
      ret=max(ret,min(fr[ls],mid-L+1)+min(fl[rs],R-mid));/////
    }
    void print()
    {
      for(int i=1;i<=n;i++)
        printf("%d ",qry(1,n,1,i,i));
      puts("");
    }
    int main()
    {
      n=rdn(); m=rdn(); tot=1; build(1,n,1);
      for(int i=1,op,l,r,l1,r1,d,k;i<=m;i++)
        {
          op=rdn(); l=rdn(); r=rdn();
          if(!op)
        {
          mdfy(1,n,1,l,r,0);
        }
          if(op==1)
        {
          l1=rdn(); r1=rdn();
          d=qry(1,n,1,l,r); if(!d)continue;
          mdfy(1,n,1,l,r,0);  k=qry(1,n,1,l1,r1);
          if(r1-l1+1-k<=d) mdfy(1,n,1,l1,r1,1);
          else
            {
              k=fnd(1,n,1,l1,r1,d);
              mdfy(1,n,1,l1,k,1);
            }
        }
          if(op==2)
        {
          printf("%d
    ",query(1,n,1,l,r));
        }
        }
      return 0;
    }

    附上暴力和maker和对拍,以便之后查。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=2e5+5;
    int n,m,ans;
    bool a[N];
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    int main()
    {
      n=rdn(); m=rdn(); for(int i=1;i<=n;i++)a[i]=1;
      for(int i=1,op,l,r,l1,r1,d;i<=m;i++)
        {
          op=rdn(); l=rdn(); r=rdn();
          if(!op)
        {
          for(int j=l;j<=r;j++)a[j]=0;
        }
          if(op==1)
        {
          l1=rdn(); r1=rdn(); d=0;
          for(int j=l;j<=r;j++)d+=a[j],a[j]=0;
          for(int j=l1;j<=r1&&d;j++)
            d-=(!a[j]),a[j]=1;
        }
          if(op==2)
        {
          d=0; ans=0;
          for(int j=l;j<=r;j++)
              if(!a[j])d++;
              else ans=max(ans,d),d=0;
          ans=max(ans,d);
          printf("%d
    ",ans);
        }
        }
      return 0;
    }
    暴力
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<ctime>
    using namespace std;
    const int N=2e5,M=10;
    int n,m,op,l,r;
    int main()
    {
      srand(time(0));
      n=rand()%N+1; m=rand()%N+1;
      printf("%d %d
    ",n,m);
      for(int i=1;i<=m;i++)
        {
          op=rand()%M;
          if(op>=3)op=2;
          l=rand()%n+1; r=rand()%n+1;
          if(l>r)swap(l,r);
          if(op==1)
        {
          printf("%d %d %d ",op,l,r);
          l=rand()%n+1; r=rand()%n+1;
          if(l>r)swap(l,r);
          printf("%d %d
    ",l,r);
        }
          else printf("%d %d %d
    ",op,l,r);
        }
      return 0;
    }
    maker
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int cnt;
    int main()
    {
      while(1)
        {
          system("./maker > data.in");
          system("./a < data.in > zj.out");
          system("./b < data.in > bl.out");
          if(system("diff zj.out bl.out"))return 0;
          cnt++; printf("cnt=%d
    ",cnt);
          if(cnt==500)return 0;
        }
    }
    对拍
  • 相关阅读:
    蓝桥杯基础练习 杨辉三角形
    蓝桥杯基础练习 回文数 特殊的数字
    普及图论三题 P1807 P1113 P 4017
    P3916 图的遍历
    [转载][总结]图论入门:建图,DFS,BFS,拓扑排序
    如何转载博客园的文章
    P1892 [BOI2003]团伙
    P1621 集合
    [模板]线性筛素数(欧拉筛)
    P5076 普通二叉树(简化版)
  • 原文地址:https://www.cnblogs.com/Narh/p/9868239.html
Copyright © 2020-2023  润新知