(线段树+并查集) Codeforces Round #416 (Div. 2) E Vladik and Entertaining Flags

Posted 惜取少年时

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(线段树+并查集) Codeforces Round #416 (Div. 2) E Vladik and Entertaining Flags相关的知识,希望对你有一定的参考价值。

In his spare time Vladik estimates beauty of the flags.

Every flag could be represented as the matrix n?×?m which consists of positive integers.

Let‘s define the beauty of the flag as number of components in its matrix. We call component a set of cells with same numbers and between any pair of cells from that set there exists a path through adjacent cells from same component. Here is the example of the partitioning some flag matrix into components:

技术分享

But this time he decided to change something in the process. Now he wants to estimate not the entire flag, but some segment. Segment of flag can be described as a submatrix of the flag matrix with opposite corners at (1,?l) and (n,?r), where conditions 1?≤?l?≤?r?≤?m are satisfied.

Help Vladik to calculate the beauty for some segments of the given flag.

Input

First line contains three space-separated integers nmq (1?≤?n?≤?10, 1?≤?m,?q?≤?105) — dimensions of flag matrix and number of segments respectively.

Each of next n lines contains m space-separated integers — description of flag matrix. All elements of flag matrix is positive integers not exceeding 106.

Each of next q lines contains two space-separated integers lr (1?≤?l?≤?r?≤?m) — borders of segment which beauty Vladik wants to know.

Output

For each segment print the result on the corresponding line.

Example

Input
4 5 4
1 1 1 1 1
1 2 2 3 3
1 1 1 2 5
4 4 5 5 5
1 5
2 5
1 2
4 5
Output
6
7
3
4

Note

Partitioning on components for every segment from first test case:

技术分享

 

线段树维护每个矩形边缘的情况,合并时利用并查集。

  1 #include <iostream>
  2 #include <string>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <queue>
  8 #include <set>
  9 #include <map>
 10 #include <list>
 11 #include <vector>
 12 #include <stack>
 13 #define mp make_pair
 14 #define MIN(a,b) (a>b?b:a)
 15 #define rank rankk
 16 //#define MAX(a,b) (a>b?a:b)
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 const int MAX=1e5+5;
 20 const ll INF=9223372036854775807;
 21 const int N=12;
 22 using namespace std;
 23 const int MOD=1e9+7;
 24 typedef pair<int,int> pii;
 25 const double eps=0.000000001;
 26 int par[MAX];
 27 int a[N][MAX];
 28 int n,m,q;
 29 int id[N<<1];
 30 int find(int x)
 31 {
 32     if(x==par[x])
 33         return x;
 34     return par[x]=find(par[x]);
 35 }
 36 void unite(int x,int y)
 37 {
 38     x=find(x);y=find(y);
 39     par[x]=y;
 40 }
 41 bool same(int x,int y)
 42 {
 43     return find(x)==find(y);
 44 }
 45 struct node
 46 {
 47     int l[N],r[N],sum;//l值在[1,n],r的值在[n+1,2n]
 48 }b[MAX<<2];
 49 void merge(node &lson,node &rson,node &rt,int lright,int rleft)
 50 {
 51     rt.sum=lson.sum+rson.sum;
 52     for(int i=1;i<=n;i++)
 53     {
 54         par[i]=lson.l[i];
 55         par[i+n]=lson.r[i];
 56         par[i+2*n]=rson.l[i]+2*n;
 57         par[i+3*n]=rson.r[i]+2*n;
 58     }
 59     for(int i=1;i<=n;i++)
 60     {
 61         if(a[i][lright]==a[i][rleft]&&!same(i+n,i+2*n))
 62         {
 63             --rt.sum;
 64             unite(i+n,i+2*n);
 65         }
 66     }
 67     for(int i=1;i<=4*n;i++)
 68     {
 69         par[i]=find(par[i]);
 70         id[par[i]]=-1;
 71     }
 72     for(int i=1;i<=n;i++)
 73     {
 74         if(id[par[i]]==-1)
 75             id[par[i]]=i;
 76         rt.l[i]=id[par[i]];
 77     }
 78     for(int i=3*n+1;i<=4*n;i++)
 79     {
 80         if(id[par[i]]==-1)
 81             id[par[i]]=i-2*n;
 82         rt.r[i-3*n]=id[par[i]];
 83     }
 84 }
 85 void build(int l,int r,int k)
 86 {
 87     if(l==r)
 88     {
 89         b[k].sum=0;
 90         for(int i=1;i<=n;i++)
 91         {
 92             if(i==1||a[i-1][l]!=a[i][l])
 93             {
 94                 b[k].l[i]=b[k].r[i]=i;
 95                 ++b[k].sum;
 96             }
 97             else
 98                 b[k].l[i]=b[k].r[i]=b[k].l[i-1];
 99         }
100         return ;
101     }
102     int mid=(l+r)/2;
103     build(l,mid,2*k);
104     build(mid+1,r,2*k+1);
105     merge(b[2*k],b[2*k+1],b[k],mid,mid+1);
106 }
107 void query(int ql,int qr,int l,int r,int k,node &ans)
108 {
109     if(l>=ql&&r<=qr)
110     {
111         ans=b[k];return;
112     }
113     int mid=(l+r)/2;
114     if(qr<=mid)
115         query(ql,qr,l,mid,2*k,ans);
116     else if(ql>mid)
117         query(ql,qr,mid+1,r,2*k+1,ans);
118     else
119     {
120         node p,q;
121         query(ql,qr,l,mid,2*k,p);
122         query(ql,qr,mid+1,r,2*k+1,q);
123         merge(p,q,ans,mid,mid+1);
124     }
125 }
126 int main()
127 {
128     int qs;
129     scanf("%d%d%d",&n,&m,&qs);
130     for(int i=1;i<=n;i++)
131         for(int j=1;j<=m;j++)
132             scanf("%d",&a[i][j]);
133     build(1,m,1);
134     node an;
135     int i;
136     for(i=1;i<=qs;i++)
137     {
138         int ls,rs;
139         scanf("%d%d",&ls,&rs);
140         query(ls,rs,1,m,1,an);
141         printf("%d\n",an.sum);
142     }
143     return 0;
144 }

 












以上是关于(线段树+并查集) Codeforces Round #416 (Div. 2) E Vladik and Entertaining Flags的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #423 (Div. 2) C 思维,并查集 或 线段树 D 树构造,水

Codeforces.1051G.Distinctification(线段树合并 并查集)

Codeforces811EVladik and Entertaining Flags [线段树][并查集]

(线段树+并查集) Codeforces Round #416 (Div. 2) E Vladik and Entertaining Flags

Codeforces 938G 线段树分治 线性基 可撤销并查集

并查集 + 线段树 LA 4730 Kingdom