树套树

好久都没有写过这个东西有点忘了啊。。。

重新学习了一波。。。

这个东西其实挺好理解也挺好写的

树套树是不支持区间修改的。。。

传统的区间加,区间查询可以用差分转化成单点修改

所以就不存在线段树上打lazy标记这个操作了(因为如果可以这么做就直接差分了)

1.线段树套线段树

2.线段树套平衡树

 #updata 11.7

上次没写。。

今天复习一下。。

上面说的 不支持区间修改上次听别人说的。。(区间修改的定义是两维都区间修改)

发现并不是这么一回事情

如果这个标记,可以永久化(也就是与时间顺序无关),那么可以支持区间修改

比如加法,单纯的取max 这些都是可以的

当然我觉得如果可以标记永久化就标记永久化比较好(写成down是可以的)

以区间加举例 怎么实现

注意现在由于我们要查找区间和,所以要分成两部分来处理

1.子树中的标记产生的影响

2.父亲上的标记产生的影响

修改:

对于1,我们每次要把路径上的点的对应区间都加上子树产生的贡献(相当于updata)sum1

对于2,我们在找到对应区间之后,给他标记一个修改值sum2

查询:

对于1,就是对应区间的sum1的和

对于2,就是父亲方向所有的sum2*区间长度

由于我没有在网上找到这题就不写了。。

BZOJ1513 和这题其实差不多的。。

注意他那个区间赋值本来是个时间依赖的操作

但是他保证了是不断变大的 所以等价于取max 就不是时间依赖了

luogu3332 zjoi k大数查询

这个是经典题目了

我们发现他其实并不是区间修改,因为一维是单点

感觉上把单点修改的放在第一维比较简单

这样就可以直接第二维上二分了

另外在第二维上也用了区间修改区间查询的标记永久化的方法

刚开始主席树儿子写了x*2 re。。

然后发现root数组需要8倍。。因为有负数

然后发现那个另外一个数组是log^2的。。。。

所以线段树套线段树 一般也就只能解决5e4了

再上去空间就炸了

时间已经接近上限

但是如果时限3s这种然后卡空间可以考虑线段树套平衡树

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
#define rg register 
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define ll long long
#define me(x) memset(x,0,sizeof(x))
#define setit set<int>::iterator
#define mp(x,y) make_pair(x,y)
#define fi first
#define se second
#define mid ((h+t)>>1)
#define mid2 ((h+t+1)>>1)
#define lowbit(x) (x&(-x))
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>IL void read(T &x)
{
  rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
  while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
}
char sr[1<<24],z[20]; int Z,C=-1;
template<class T>IL void wer(T x)
{
  if (x<0) sr[++C]='-',x=-x;
  while (z[++Z]=x%10+48,x/=10);
  while (sr[++C]=z[Z],--Z);
}
IL void wer1()
{
  sr[++C]=' ';
}
IL void wer2()
{
  sr[++C]='\n';
}
template<class T>IL void maxa(T &x,T y)
{
  if (x<y) x=y;
}
template<class T>IL void mina(T &x,T y)
{
  if (x>y) x=y;
}
template<class T>IL T MAX(T x,T y)
{
  return x>y?x:y;
}
template<class T>IL T MIN(T x,T y)
{
  return x<y?x:y;
}
const int INF=1e9;
const int N=5e4+1e3;
const int N2=N*300;
int n,m;
struct sgt2{
  int ls[N2],rs[N2],lazy[N2],cnt;
  ll sum[N2];
  void change(int &x,int h,int t,int h1,int t1)
  {
    if (!x) x=++cnt;
    if (h1<=h&&t<=t1)
    {
      lazy[x]++; return;
    }
    sum[x]+=MIN(t1,t)-MAX(h1,h)+1;
    if (h1<=mid) change(ls[x],h,mid,h1,t1);
    if (mid<t1) change(rs[x],mid+1,t,h1,t1);
  }
  ll query(int x,int h,int t,int h1,int t1,int k)
  {
    k+=lazy[x];
    if (h1<=h&&t<=t1)
    {
      return sum[x]+1ll*(t-h+1)*k;
    }
    ll ans=0;
    if (h1<=mid) ans+=query(ls[x],h,mid,h1,t1,k);
    if (mid<t1) ans+=query(rs[x],mid+1,t,h1,t1,k);
    return ans;
  }
}S2;
struct sgt{
  int root[N*8];
  void change(int x,int h,int t,int pos,int x1,int y1)
  {
    S2.change(root[x],1,n,x1,y1); 
    if (h==t) return;
    if (pos<=mid) change(x*2,h,mid,pos,x1,y1);
    else change(x*2+1,mid+1,t,pos,x1,y1);
  }
  int query(int x,int h,int t,int x1,int y1,ll k)
  {
    if (h==t) return h;
    ll ans=S2.query(root[x*2+1],1,n,x1,y1,0);
    if (ans<k) return query(x*2,h,mid,x1,y1,k-ans);
    else return query(x*2+1,mid+1,t,x1,y1,k);
  }
}S1;
int main()
{
  read(n); read(m);
  rep(i,1,m)
  {
    int kk,x,y;
    ll z;
    read(kk); read(x); read(y); read(z);
    if (kk==1)
    {
      S1.change(1,-N,N,z,x,y);
    } else
    {
      int ans=S1.query(1,-N,N,x,y,z);
      if (ans==-N) wer(0);
      else wer(ans);
      wer2();
    }
  }
  fwrite(sr,1,C+1,stdout);
  return 0;
}

 

bzoj4604

bzo3065

posted @ 2018-11-07 13:48  尹吴潇  阅读(168)  评论(0编辑  收藏  举报