警示后人
查看原帖
警示后人
310317
lzytag楼主2022/10/21 23:09

二维线段树写的时候一定要注意节省空间啊!

有两点建议

  1. 所有数全开int,运算时乘上1ll
  2. 线段树节点只存一个值,其他的值由这个值推出

附上代码片段

struct Node{
	int val;
};
Node operator + (Node i,Node j)
{
	return Node{(1ll*i.val*j.val%Mod+
				1ll*(1-i.val+Mod)*(1-j.val+Mod)%Mod)%Mod}; 
}
int rt[MaxN*4],son[MaxN*400][2],cnt;
Node tr[MaxN*400];
int newnd()
{
	tr[++cnt] = Node{1}; 
	return cnt;
}
int upd(int c,int l,int r,int ql,int qr,Node x)
{
	if(c == 0) c = newnd();
	if(l == ql && r == qr) return tr[c] = tr[c] + x,c;
	int mid = l+r>>1;
	if(ql > mid) son[c][1] = upd(son[c][1],mid+1,r,ql,qr,x);
	else if(qr <= mid) son[c][0] = upd(son[c][0],l,mid,ql,qr,x);
	else son[c][0] = upd(son[c][0],l,mid,ql,mid,x),son[c][1] = upd(son[c][1],mid+1,r,mid+1,qr,x);
	return c; 
}
void Upd(int c,int l,int r,int xl,int xr,int yl,int yr,Node x)
{
	if(xl > xr || yl > yr) return ;
	if(l == xl && r == xr) return rt[c] = upd(rt[c],1,n,yl,yr,x),void();
	int mid = l+r>>1;
	if(xl > mid) Upd(c<<1|1,mid+1,r,xl,xr,yl,yr,x);
	else if(mid >= xr) Upd(c<<1,l,mid,xl,xr,yl,yr,x);
	else Upd(c<<1,l,mid,xl,mid,yl,yr,x),Upd(c<<1|1,mid+1,r,mid+1,xr,yl,yr,x);
}
Node qry(int c,int l,int r,int x)
{
	if(!c) return Node{1};
	if(l == r) return tr[c];
	int mid = l+r>>1;
	if(mid < x) return tr[c]+qry(son[c][1],mid+1,r,x);
	else return tr[c]+qry(son[c][0],l,mid,x);
}
Node Qry(int c,int l,int r,int x,int y)
{
	if(l == r) return qry(rt[c],1,n,y);
	int mid = l+r>>1;
	if(mid < x) return qry(rt[c],1,n,y)+Qry(c<<1|1,mid+1,r,x,y);
	else return qry(rt[c],1,n,y)+Qry(c<<1,l,mid,x,y); 
}

卡了一个晚上,麻了。

2022/10/21 23:09
加载中...