zoukankan      html  css  js  c++  java
  • poj 3667

    题解:

    想的和标算不是很一样

    标算实现起来应该比较简单吧

    我的做法:

    对每个点维护一个值代表它能向左延伸的最大位置

    然后查询时在线段树上二分nlogn

    那么修改怎么进行呢

    从向左延伸到的最大位置到当前位置修改为等差数列,这个操作用到的还是挺多的

    将覆盖的这一段修改为0

    维护区间最大值就可以了

    不小心把change的条件写成了else也不知道怎么想的

    本来以为这个应该慢一点,事实上差不多,可能是因为down和updata比较简单

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define IL inline
    #define rint register int
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    char ss[1<<24],*A=ss,*B=ss;
    IL char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;}
    template<class T>void read(T&x){
        rint f=1,c;while(c=gc(),c<48||57<c)if(c=='-')f=-1;x=c^48;
        while(c=gc(),47<c&&c<58)x=(x<<3)+(x<<1)+(c^48);x*=f;
    }
    const int N=6e4;
    int ph[N*4],pt[N*4],lazy[N*4],maxa[N*4],mina[N*4],n,m;
    IL int max(int x,int y)
    {
      if (x>y) return(x); else return(y);
    }
    IL int min(int x,int y)
    {
      if (x<y) return(x); else return(y); 
    }
    IL void updata(int x)
    {
      maxa[x]=max(maxa[x*2],maxa[x*2+1]);
      mina[x]=min(mina[x*2],mina[x*2+1]);
    }
    IL void down(int x)
    {
      if (!lazy[x]) return;
      lazy[x*2]=lazy[x*2+1]=lazy[x];
      if(lazy[x]!=-1)
      {
        maxa[x*2]=lazy[x]-ph[x];
        mina[x*2]=lazy[x]-pt[x];
        maxa[x*2+1]=lazy[x]-ph[x*2+1];
        mina[x*2+1]=lazy[x]-pt[x*2+1];
      } else mina[x*2]=mina[x*2+1]=maxa[x*2]=maxa[x*2+1]=-1;
      lazy[x]=0;
    }
    #define mid ((h+t)/2)
    void build(int x,int h,int t)
    {
      ph[x]=h; pt[x]=t;
      if (h==t) return;
      build(x*2,h,mid); build(x*2+1,mid+1,t);
    }
    void change(int x,int h,int t,int h1,int t1)
    {
      if (h1<=h&&t<=t1)
      { 
        lazy[x]=maxa[x]=mina[x]=-1;
        return;
      }
      down(x);
      if (h1<=mid) change(x*2,h,mid,h1,t1);
      if (mid<t1) change(x*2+1,mid+1,t,h1,t1);
      updata(x);
    }
    void change2(int x,int h,int t,int h1,int t1,int k)
    {
      if (h1<=h&&t<=t1)
      {
        lazy[x]=k; maxa[x]=k-h; mina[x]=k-t;
        return;
      }
      down(x);
      if (h1<=mid) change2(x*2,h,mid,h1,t1,k);
      if (mid<t1) change2(x*2+1,mid+1,t,h1,t1,k); 
      updata(x);
    }
    int query(int x,int h,int t,int pos)
    {
      if (h==t) return(maxa[x]);
      down(x);
      if (pos<=mid) return(query(x*2,h,mid,pos));
      else return(query(x*2+1,mid+1,t,pos));
    }
    vector<int> ve;
    void query3(int x,int h,int t,int h1,int t1)
    {
      if(h1<=h&&t<=t1)
      { 
        ve.push_back(x);
        return;
      }
      down(x);
      if (h1<=mid) query3(x*2,h,mid,h1,t1);
      if (mid<t1) query3(x*2+1,mid+1,t,h1,t1);
    }
    int query4(int x,int h,int t)
    {
      if (h==t) return(h);
      down(x);
      if (mina[x*2+1]==-1) return(query4(x*2+1,mid+1,t));
      else return(query4(x*2,h,mid));
    }
    int query2(int k)
    {
      if (k==0) return(1); 
      ve.clear();
      query3(1,1,n,1,k);
      dep(i,ve.size()-1,0)
      {
        int x=ve[i];
        if (mina[x]==-1)
          return ((query4(x,ph[x],pt[x]))+1);
      }
      return(1);
    }
    int query1(int x,int h,int t,int pos)
    {
      if (maxa[x]<pos) return(-1);
      if (h==t) return(h);
      down(x);
      int ans1=query1(x*2,h,mid,pos);
      if (ans1!=-1) return(ans1);
      return(query1(x*2+1,mid+1,t,pos)); 
    }
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      read(n); read(m);
      build(1,1,n);
      change2(1,1,n,1,n,n+1);
      rep(i,1,m)
      {
        int x,y,z;
        read(x);
        if(x==1)
        {
          read(y);
          int xx=query1(1,1,n,y);
          if (xx==-1)
          { 
            printf("0
    ");
          }
          else
          { 
            printf("%d
    ",xx);
            int yy=query2(xx-1);
            if (yy<=xx-1) change2(1,1,n,yy,xx-1,xx);
            change(1,1,n,xx,xx+y-1);
          }
        } else
        {
          read(y); read(z); z=z+y-1;
          int xx=query(1,1,n,z+1);
          if (xx==-1) xx=z; else xx+=z;
          xx=min(xx,n);
          int yy=query2(y-1);
          if (yy<=xx) change2(1,1,n,yy,xx,xx+1);
        }
      }
      return 0;
    }

    标算:

    对每个节点维护max_pre max_scc

    这个也可以用平衡树来实现,这样删除节点就可以直接加一个新节点

    但我觉得这应该还是挺慢的??

    有空也写一下

    等我写了再详细写吧。。

    刚开始发现query里没有比较max_sum

    应该直接掉成o(n)

    然后就炸了

    gdb watch真好用

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    char ss[1<<24],*A=ss,*B=ss;
    IL char gc()
    {
      return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
    }
    template<class T> void read(T &x)
    {
      rint f=1,c;
      while (c=gc(),c<48||57<c) if (c=='-') f=-1; x=c^48;
      while (c=gc(),47<c&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
    }
    const int N=6e4;
    int max_scc[N*4],max_pre[N*4],max_sum[N*4],lazy[N*4],n,m;
    #define mid ((h+t)/2)
    int maxb(int a,int b,int c)
    {
      return(max(c,max(a,b)));
    }
    IL void updata(int x,int h,int t)
    {
      max_sum[x]=maxb(max_scc[x*2]+max_pre[x*2+1],max_sum[x*2],max_sum[x*2+1]);
      max_pre[x]=max_pre[x*2]==(mid-h+1)?max_pre[x*2]+max_pre[x*2+1]:max_pre[x*2];
      max_scc[x]=max_scc[x*2+1]==(t-mid)?max_scc[x*2+1]+max_scc[x*2]:max_scc[x*2+1]; 
    }
    IL void down(int x,int h,int t)
    {
      if (!lazy[x]) return;
      if (lazy[x]==1)
      {
        lazy[x*2]=lazy[x*2+1]=1;
        max_pre[x*2]=max_scc[x*2]=max_sum[x*2]=mid-h+1;
        max_pre[x*2+1]=max_scc[x*2+1]=max_sum[x*2+1]=t-mid;
      } else
      {
        lazy[x*2]=lazy[x*2+1]=-1;
        max_pre[x*2]=max_scc[x*2]=
        max_pre[x*2+1]=max_scc[x*2+1]=
        max_sum[x*2]=max_sum[x*2+1]=0;
      }
      lazy[x]=0;
    }
    void build(int x,int h,int t)
    {
      max_pre[x]=max_scc[x]=max_sum[x]=t-h+1;
      if (h==t) return;
      build(x*2,h,mid); build(x*2+1,mid+1,t);
    }
    void change(int x,int h,int t,int h1,int t1,bool k)
    {
      if (h1<=h&&t<=t1)
      {
        if (k==1) lazy[x]=1,max_pre[x]=max_scc[x]=max_sum[x]=t-h+1;
        else lazy[x]=-1,max_pre[x]=max_scc[x]=max_sum[x]=0;
        return;
      }
      down(x,h,t);
      if (h1<=mid) change(x*2,h,mid,h1,t1,k);
      if (mid<t1) change(x*2+1,mid+1,t,h1,t1,k);
      updata(x,h,t);
    }
    int query(int x,int h,int t,int last,int k)
    {
      if (max_pre[x]+last>=k) return(h+k-last-1);
      if (max_sum[x]<k) return(-1);
      if (h==t) return(-1);
      down(x,h,t); 
      int xx=query(x*2,h,mid,0,k);
      if (xx!=-1) return(xx);
      int tmp=max_scc[x*2]==(mid-h+1)?max_scc[x*2]+last:max_scc[x*2];
      return(query(x*2+1,mid+1,t,tmp,k));
    }
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      read(n); read(m);
      build(1,1,n);
      rep(i,1,m)
      {
        int x,y,z;
        read(x);
        if (x==1)
        {
          read(y);
          int xx=query(1,1,n,0,y);
          if (xx==-1)
          {
            printf("0
    ");
          } else
          {
            printf("%d
    ",xx-y+1);
            change(1,1,n,xx-y+1,xx,0);
          }
        } else
        {
          read(y); read(z);
          change(1,1,n,y,y+z-1,1);
        }
      }
      return 0;
    }
  • 相关阅读:
    linux 常用命令
    restframeword之视图,解析器
    restframework之序列化
    restframeword之APIview
    MongoDB
    redis
    mysql优化
    (java)图片像素的操作
    关于java AudioInputStream播放短音频没声音的问题
    java向文件中追加内容的一种简单方式
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9086056.html
Copyright © 2011-2022 走看看