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 ≤ 101 ≤ 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:


分析:n很小不超過10,考慮直接上線段樹,線段樹上的每個點上保存當前這個線段的左右兩端的連通性,每次兩個線段合併時用並查集就可以了,我寫合併操作時用了面向沒有對象的思想,把合併操作作爲線段類的一個方法,雖然似乎並沒有什麼卵用。

#include<bits/stdc++.h>
#define N 15
#define M 100005
using namespace std;
int n,m,x,y,q,cnt,fa[N*M],a[N][M];
int Find(int x)
{
    if(fa[x] == x) return x;
    fa[x] = Find(fa[x]);
    return fa[x];
}
struct segment
{
    int l[N],r[N],tot;
    void _merge(segment ls,segment rs,int k)
    {
        for(int i = 1;i <= n;i++)
        {
            fa[ls.l[i]] = ls.l[i];
            fa[ls.r[i]] = ls.r[i];
            fa[rs.l[i]] = rs.l[i];
            fa[rs.r[i]] = rs.r[i];
        }
        tot = ls.tot + rs.tot;
        for(int i = 1;i <= n;i++)
         if(a[i][k] == a[i][k+1])
         {
             int al = Find(ls.r[i]),ar = Find(rs.l[i]);
             if(al != ar)
             {
                 tot--;
                 fa[al] = ar;
             }
         }
         for(int i = 1;i <= n;i++) l[i] = Find(ls.l[i]),r[i] = Find(rs.r[i]);
    }
}tr[4*M];
void Build(int i,int l,int r)
{
    if(l == r)
    {
        for(int j = 1;j <= n;j++)
         if(a[j][l] != a[j-1][l]) tr[i].l[j] = tr[i].r[j] = ++cnt,tr[i].tot++;
         else tr[i].l[j] = tr[i].r[j] = tr[i].l[j-1];
        return;
    }
    int mid = (l+r)>>1;
    Build(2*i,l,mid);
    Build(2*i+1,mid+1,r);
    tr[i]._merge(tr[2*i],tr[2*i+1],mid);
}
segment Query(int i,int l,int r,int x,int y)
{
    if(l == x && r == y) return tr[i];
    int mid = (l+r)>>1;
    if(y <= mid) return Query(2*i,l,mid,x,y);
    else
     if(x <= mid)
     {
        segment temp;
        temp._merge(Query(2*i,l,mid,x,mid),Query(2*i+1,mid+1,r,mid+1,y),mid);
        return temp;
     }
     else return Query(2*i+1,mid+1,r,x,y);
}
int main()
{
    cin.sync_with_stdio(false);
    cin>>n>>m>>q;
    for(int i = 1;i <= n;i++)
     for(int j = 1;j <= m;j++)
      cin>>a[i][j];
    Build(1,1,m);
    for(int i = 1;i <= q;i++)
    {
        cin>>x>>y;
        cout<<Query(1,1,m,x,y).tot<<endl;
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章