树套树

Description

一个 \(N*M\) 的方格,初始时每个格子有一个整数权值,接下来每次有 \(2\) 个操作:

  • 改变一个格子的权值
  • 求一个子矩阵中某个特定权值出现的个数

Input

每一行有两个数字 \(N,M\)。接下来N行,每行 \(M\) 个数字。第 \(i+1\) 行第 \(j\) 个数字表示格子 \((i,j)\) 的初值。

接下来输入一个 \(Q\),后面 \(Q\) 行每行描述一个操作。

  • 操作1:
    1 x y c,表示将格子(x,y)的值变为c
  • 操作2:
    2 x1 x2 y1 y2 c,表示询问所有满足格子中数字为c的格子数字

(n,m<=300,Q<=5000)

(1<=x<=N,1<=y<=M,1<=c<=100)

(x1<=x<=x2,y1<=y<=y2)

Output

对于每个操作 \(2\),按输入中出现的顺序,依次输出一行一个整数表示所求得的个数。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e2+5;
int n,m,q;
int v[N][N],a[105][N][N];
inline int lowbit(int x){
	return x&-x;
}
void add(int c,int x,int y,int k){
	for(int i=x;i<N;i+=lowbit(i))
		for(int j=y;j<N;j+=lowbit(j))
			a[c][i][j]+=k;
	return;
}
int find(int c,int x,int y){
	int res=0;
	for(int i=x;i>0;i-=lowbit(i))
		for(int j=y;j>0;j-=lowbit(j))
			res+=a[c][i][j];
	return res;
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			cin>>v[i][j];
			add(v[i][j],i,j,1);
		}
	cin>>q;
	while(q--){
		int op,x,y,l,r,c;
		cin>>op;
		if(op==1){
			cin>>x>>y>>c;
			add(v[x][y],x,y,-1);
			add(c,x,y,1);
			v[x][y]=c;
		}
		if(op==2){
			cin>>x>>l>>y>>r>>c;
			cout<<find(c,l,r)+find(c,x-1,y-1)-find(c,l,y-1)-find(c,x-1,r)<<'\n';
		}
	}
	return 0;
}
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e2+5;
int n,m,q;
int v[N][N];
struct tree_Y{
	int a[N];
	int v;
	int lowbit(int x){
		return x&-x;
	}
	tree_Y(){
		memset(a,0,sizeof(a));
		this->v=301;
	}
	void add(int x,int f){
		while(x<v){
			a[x]+=f;
			x+=lowbit(x);
		}
		return;
	}
	int find(int x){
		int res=0;
		while(x>0){
			res+=a[x];
			x-=lowbit(x);
		}
		return res;
	}
}a[N][N];
int lowbit(int x){
	return x&-x;
}
void add(int c,int x,int y,int k){
	for(int i=x;i<N;i+=lowbit(i))
		a[c][i].add(y,k);
	return;
}
int find(int c,int x,int y){
	int res=0;
	for(int i=x;i>0;i-=lowbit(i))
		res+=a[c][i].find(y);
	return res;
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			cin>>v[i][j];
			add(v[i][j],i,j,1);
		}
	cin>>q;
	while(q--){
		int op,x,y,l,r,c;
		cin>>op;
		if(op==1){
			cin>>x>>y>>c;
			add(v[x][y],x,y,-1);
			add(c,x,y,1);
			v[x][y]=c;
		}
		if(op==2){
			cin>>x>>l>>y>>r>>c;
			cout<<find(c,l,r)+find(c,x-1,y-1)-find(c,l,y-1)-find(c,x-1,r)<<'\n';
		}
	}
	return 0;
}
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e2+5;
int n,m,q;
int v[N][N];
struct tree_Y{
	int a[N];
	int v;
	int lowbit(int x){
		return x&-x;
	}
	tree_Y(){
		memset(a,0,sizeof(a));
		this->v=301;
	}
	void add(int x,int f){
		while(x<v){
			a[x]+=f;
			x+=lowbit(x);
		}
		return;
	}
	int find(int x){
		int res=0;
		while(x>0){
			res+=a[x];
			x-=lowbit(x);
		}
		return res;
	}
};
struct tree_X{
	tree_Y a[N];
	int v;
	int lowbit(int x){
		return x&-x;
	}
	tree_X(){
		this->v=301;
	}
	void add(int x,int y,int f){
		while(x<v){
			a[x].add(y,f);
			x+=lowbit(x);
		}
		return;
	}
	int find(int x,int y){
		int res=0;
		while(x>0){
			res+=a[x].find(y);
			x-=lowbit(x);
		}
		return res;
	}
}a[N];
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			cin>>v[i][j];
			a[v[i][j]].add(i,j,1);
		}
	cin>>q;
	while(q--){
		int op,x,y,l,r,c;
		cin>>op;
		if(op==1){
			cin>>x>>y>>c;
			a[v[x][y]].add(x,y,-1);
			a[c].add(x,y,1);
			v[x][y]=c;
		}
		if(op==2){
			cin>>x>>l>>y>>r>>c;
			cout<<a[c].find(l,r)+a[c].find(x-1,y-1)-a[c].find(l,y-1)-a[c].find(x-1,r)<<'\n';
		}
	}
	return 0;
}
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e2+5;
int n,m,q;
int v[N][N];
struct tree_Y{
	int l,r;
	int sum;
	tree_Y *pl,*pr;
	tree_Y(int ll,int rr):l(ll),r(rr),sum(0),pl(nullptr),pr(nullptr){}
	void add(int y,int k){
		if(l==r){
			sum+=k;
			return;
		}
		int mid=l+r>>1;
		if(y<=mid){
			if(!pl)	pl=new tree_Y(l,mid);
			pl->add(y,k);
		}
		if(y>mid){
			if(!pr)	pr=new tree_Y(mid+1,r);
			pr->add(y,k);
		}
		sum=(pl?pl->sum:0)+(pr?pr->sum:0);
		return;
	}
	int query(int x,int y){
		if(r<x||l>y)	return 0;
		if(x<=l&&r<=y)	return sum;
		int res=0;
		if(pl)	res+=pl->query(x,y);
		if(pr)	res+=pr->query(x,y);
		return res;
	}
};
struct tree_X{
	int l,r;
	tree_Y y_tree;
	tree_X *pl,*pr;
	tree_X(int ll,int rr,int m):l(ll),r(rr),y_tree(1,m),pl(nullptr),pr(nullptr){}
	void add(int x,int y,int k){
		if(l==r){
			y_tree.add(y,k);
			return;
		}
		int mid=l+r>>1;
		if(x<=mid){
			if(!pl)	pl=new tree_X(l,mid,m);
			pl->add(x,y,k);
		}
		if(x>mid){
			if(!pr)	pr=new tree_X(mid+1,r,m);
			pr->add(x,y,k);
		}
		y_tree.add(y,k);
		return;
	}
	int query(int x1,int y1,int x2,int y2){
		if(r<x1||l>y1)	return 0;
		if(x1<=l&&r<=y1)	return y_tree.query(x2,y2);
		int res=0;
		if(pl)	res+=pl->query(x1,y1,x2,y2);
		if(pr)	res+=pr->query(x1,y1,x2,y2);
		return res;
	}
}*a[N];
signed main(){
	cin>>n>>m;
	for(int i=1;i<=100;i++)
		a[i]=new tree_X(1,n,m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			cin>>v[i][j];
			a[v[i][j]]->add(i,j,1);
		}
	cin>>q;
	while(q--){
		int op,x,y,l,r,c;
		cin>>op;
		if(op==1){
			cin>>x>>y>>c;
			a[v[x][y]]->add(x,y,-1);
			a[c]->add(x,y,1);
			v[x][y]=c;
		}
		if(op==2){
			cin>>x>>l>>y>>r>>c;
			cout<<a[c]->query(x,y,l,r)<<'\n';
		}
	}
	return 0;
}
posted @ 2026-01-29 21:49  concert_b  阅读(1)  评论(0)    收藏  举报