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;
}
原文地址:https://www.cnblogs.com/yinwuxiao/p/9086056.html