二维线段树,稍微学了一下,写个博客,留个板子,日后忘了看。
二维线段树,树套数写法,四叉树没写
单点更新,区间查询最大值最小值。
#include
using namespace std;
typedef long long ll;
const int N=1005;
int maxx[N*4][N*4],minn[N*4][N*4],a[N][N];
int n,m,Mx,Mi;
void pushup(int px,int py) {
maxx[px][py]=max(maxx[px][py*2],maxx[px][py*2+1]);
minn[px][py]=min(minn[px][py*2],minn[px][py*2+1]);
}
void buildy(int py,int l,int r,int px,int x) {
if(l==r) {
if(x!=-1) {
maxx[px][py]=a[x][l];
minn[px][py]=a[x][l];
} else {
maxx[px][py]=max(maxx[px*2][py],maxx[px*2+1][py]);
minn[px][py]=min(minn[px*2][py],minn[px*2+1][py]);
}
return;
}
int mid=(l+r)/2;
buildy(py*2,l,mid,px,x);
buildy(py*2+1,mid+1,r,px,x);
pushup(px,py);
}
void buildx(int px,int l,int r) {
if(l==r) {
buildy(1,1,n,px,l);
return;
}
int mid=(l+r)/2;
buildx(px*2,l,mid);
buildx(px*2+1,mid+1,r);
buildy(1,1,n,px,-1);
}
void changey(int py,int l,int r,int px,int x,int y,int val) {
if(l==r) {
if(x!=-1) {
maxx[px][py]=val;
minn[px][py]=val;
} else {
maxx[px][py]=max(maxx[px*2][py],maxx[px*2+1][py]);
minn[px][py]=min(minn[px*2][py],minn[px*2+1][py]);
}
return;
}
int mid=(l+r)/2;
if(y<=mid)changey(py*2,l,mid,px,x,y,val);
else changey(py*2+1,mid+1,r,px,x,y,val);
pushup(px,py);
}
void changex(int px,int l,int r,int x,int y,int val) {
if(l==r) {
changey(1,1,n,px,x,y,val);
return;
}
int mid=(l+r)/2;
if(x<=mid)changex(px*2,l,mid,x,y,val);
else changex(px*2+1,mid+1,r,x,y,val);
changey(1,1,n,px,-1,y,val);
}
void asky(int py,int l,int r,int px,int L,int R) {
if(L<=l&&r<=R) {
Mx=max(Mx,maxx[px][py]);
Mi=min(Mi,minn[px][py]);
return;
}
int mid=(l+r)/2;
if(L<=mid)asky(py*2,l,mid,px,L,R);
if(R>mid)asky(py*2+1,mid+1,r,px,L,R);
}
void askx(int px,int l,int r,int L,int R,int U,int D) {
if(L<=l&&r<=R) {
asky(1,1,n,px,U,D);
return;
}
int mid=(l+r)/2;
if(L<=mid)askx(px*2,l,mid,L,R,U,D);
if(R>mid)askx(px*2+1,mid+1,r,L,R,U,D);
}
int main() {
int T;
scanf("%d",&T);
for(int cas=1; cas<=T; ++cas) {
scanf("%d",&n);
for(int i=1; i<=n; ++i) {
for(int j=1; j<=n; ++j) {
scanf("%d",&a[i][j]);
}
}
buildx(1,1,n);
printf("Case #%d:\n",cas);
scanf("%d",&m);
while(m--) {
int x,y,len;
scanf("%d %d %d",&x,&y,&len);
int l=x-len/2;
int r=x+len/2;
int u=y-len/2;
int d=y+len/2;
if(l<1)l=1;
if(r>n)r=n;
if(u<1)u=1;
if(d>n)d=n;
Mx=-1,Mi=2e9;
askx(1,1,n,l,r,u,d);
int mid=(Mx+Mi)/2;
printf("%d\n",mid);
changex(1,1,n,x,y,mid);
}
}
return 0;
}
动态开点,区间更新,单点查询,标记永久化。
#include
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int N = 2e5 + 500;
int n,m;
int tot,root[N*4];
struct tree {
int l,r;
ll data;
} t[N*400];
ll quick(ll a,ll b) {
ll ans=1;
while(b) {
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
ll cal(ll p,ll q) {
ll ans=p*q%mod;
ans=(ans+(1-q)*(1-p)%mod)%mod;
ans=(ans+mod)%mod;
return ans;
}
void changey(int &p,int l,int r,int L,int R,ll val) {
if(!p) {
p=++tot;
t[p].data=1ll;
}
if(L<=l&&r<=R) {
t[p].data=cal(t[p].data,val);
return;
}
int mid=(l+r)/2;
if(L<=mid)changey(t[p].l,l,mid,L,R,val);
if(R>mid)changey(t[p].r,mid+1,r,L,R,val);
}
void changex(int p,int l,int r,int L,int R,int U,int D,ll val) {
if(L<=l&&r<=R) {
changey(root[p],1,n,U,D,val);
return;
}
int mid=(l+r)/2;
if(L<=mid)changex(p*2,l,mid,L,R,U,D,val);
if(R>mid)changex(p*2+1,mid+1,r,L,R,U,D,val);
}
ll asky(int p,int l,int r,int x) {
if(!p)return 1;
if(l==r) {
return t[p].data;
}
int mid=(l+r)/2;
if(x<=mid)return cal(t[p].data,asky(t[p].l,l,mid,x));
else return cal(t[p].data,asky(t[p].r,mid+1,r,x));
}
ll askx(int p,int l,int r,int x,int y) {
if(l==r) {
return asky(root[p],1,n,y);
}
int mid=(l+r)/2;
if(x<=mid)return cal(askx(p*2,l,mid,x,y),asky(root[p],1,n,y));
else return cal(askx(p*2+1,mid+1,r,x,y),asky(root[p],1,n,y));
}
int main() {
scanf("%d %d",&n,&m);
while(m--) {
int op,x,y;
scanf("%d %d %d",&op,&x,&y);
if(op == 1) {
ll q=quick(1ll*(y-x+1),mod-2);
if(x>1)changex(1,0,n,1,x-1,x,y,(1-q+mod)%mod),changex(1,0,n,0,0,1,x-1,0);
if(y<n)changex(1,0,n,x,y,y+1,n,(1-q+mod)%mod),changex(1,0,n,0,0,y+1,n,0);
changex(1,0,n,x,y,x,y,(1-2ll*q+mod)%mod),changex(1,0,n,0,0,x,y,q);
} else {
printf("%lld\n",askx(1,0,n,x-1,y));
}
}
return 0;
}