(线段树+并查集) 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 n, m, q (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 l, r (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
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
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