That's a good question. In the phrase of "jy gods", the essence of this question is broken. %%%
However, the maintenance information still needs more details. However, it's a piece of cake to finish the question of bzoj1018 ~because n is very small, we consider using segment trees to maintain the information of each column. When intervals are merged, we need to know the interconnection of two columns, so for each node we need to record the connectivity information of l[n],r[n], the left and right endpoints of the interval. In order to query, we also need to know the number of interval connected blocks. So maintain another tot. Considering interval merging, we can use and collect to implement O(n), and remember to re-maintain the connection between the left and right endpoints of the merged interval. Total complexity O (n (mlogm + qlogm)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,m,q,mp[11][N],fa[N*11],num=0;
struct data{
int l[11],r[11],tot;
};
struct node{
data x;
}tree[N<<2];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
data merge(int mid,data l,data r){
data res;res.tot=l.tot+r.tot;
for(int i=1;i<=n;++i){
fa[l.r[i]]=l.r[i];fa[l.l[i]]=l.l[i];
fa[r.l[i]]=r.l[i];fa[r.r[i]]=r.r[i];
}
for(int i=1;i<=n;++i)
if(mp[i][mid]==mp[i][mid+1]){
int xx=find(l.r[i]),yy=find(r.l[i]);
if(xx!=yy) fa[xx]=yy,res.tot--;
}
for(int i=1;i<=n;++i) res.l[i]=find(l.l[i]),res.r[i]=find(r.r[i]);
return res;
}
void build(int p,int l,int r){
if(l==r){
data& x=tree[p].x;x.tot=n;
for(int i=1;i<=n;++i)
if(mp[i][l]==mp[i-1][l]) x.l[i]=x.r[i]=num,x.tot--;
else x.l[i]=x.r[i]=++num;return;
}int mid=l+r>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
tree[p].x=merge(mid,tree[p<<1].x,tree[p<<1|1].x);
}
data ask(int p,int l,int r,int x,int y){
if(x<=l&&r<=y) return tree[p].x;
int mid=l+r>>1;
if(y<=mid) return ask(p<<1,l,mid,x,y);
if(x>mid) return ask(p<<1|1,mid+1,r,x,y);
return merge(mid,ask(p<<1,l,mid,x,y),ask(p<<1|1,mid+1,r,x,y));
}
int main(){
// freopen("a.in","r",stdin);
n=read();m=read();q=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) mp[i][j]=read();
build(1,1,m);
while(q--){
int x=read(),y=read();
data res=ask(1,1,m,x,y);
printf("%d\n",res.tot);
}
return 0;
}