树套树
好久都没有写过这个东西有点忘了啊。。。
重新学习了一波。。。
这个东西其实挺好理解也挺好写的
树套树是不支持区间修改的。。。
传统的区间加,区间查询可以用差分转化成单点修改
所以就不存在线段树上打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