Friday, December 14, 2018

[UVa] 11297 - Census

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : 11297 - Census
Source            : UVa Online Judge
Category          : Graph Theory
Algorithm         : Segment Tree 2D
Verdict           : Accepted 
// 2D Segment Tree
// Query  : Find maximum and minimum of a rectangle (r1,c1) -> (r2,c2)
// Update : Change value of a cell (r1,c1)
 
#include "bits/stdc++.h"
 
using namespace std;
 
#define ll                 long long
#define inf                1e17
#define pll                pair <ll, ll>
#define ff                 first
#define ss                 second
 
static const int maxn = 500 + 5;
 
int row, col;
ll grid[maxn][maxn];
pll st[maxn*4][maxn*4];
 
// here we are not changing first 3 arguments. Means, our rows are fixed.
// we narrow down to our columns, and generate segment tree for row [r1,r2] (including)
// we can pass flag instead of passing two parameters r1 and r2 (thats just optimization)/
 
void genSegTreeFrom_c1_to_c2(int parSegTree, int r1, int r2, int node, int c1, int c2)
{
    if (c1 == c2)
    {
        if (r1 == r2)
        {
            // means we are working on single row,
            // and we can directly generate segment tree for that row = r1;
            st[parSegTree][node].ff = st[parSegTree][node].ss = grid[r1][c1];
            return;
        }
        // here, parSegTree      = parent segment tree
        // (parSegTree << 1)     = left child segment tree
        // (parSegTree << 1 | 1) = right child segment tree
        // we build parent segment tree using values of children segment trees
 
        // we are creating segment tree which contains sum from row (r1 to r2)
 
        if (r1 != r2)
        {
            int leftChild = parSegTree << 1;
            int rightChild = leftChild | 1;
            st[parSegTree][node].ff = min(st[leftChild][node].ff, st[rightChild][node].ff);
            st[parSegTree][node].ss = max(st[leftChild][node].ss, st[rightChild][node].ss);
            return;
        }
    }
    int left = node << 1;
    int right = left | 1;
    int mid = (c1 + c2) >> 1;
    genSegTreeFrom_c1_to_c2(parSegTree, r1, r2, left, c1, mid);
    genSegTreeFrom_c1_to_c2(parSegTree, r1, r2, right, mid+1, c2);
    st[parSegTree][node].ff = min(st[parSegTree][left].ff, st[parSegTree][right].ff);
    st[parSegTree][node].ss = max(st[parSegTree][left].ss, st[parSegTree][right].ss);
}
 
void genSegTreeFrom_r1_to_r2(int node, int r1, int r2)
{
    // if we have narrow down to single row
    if (r1 == r2)
    {
        genSegTreeFrom_c1_to_c2(node, r1, r2, 1, 1, col);
        return;
    }
    int left = node << 1;
    int right = left | 1;
    int mid = (r1 + r2) >> 1;
    genSegTreeFrom_r1_to_r2(left, r1, mid);
    genSegTreeFrom_r1_to_r2(right, mid+1, r2);
 
    // now using upper two segment trees, we create new segment tree
    genSegTreeFrom_c1_to_c2(node, r1, r2, 1, 1, col);
}
 
void gen2DSegTree()
{
    genSegTreeFrom_r1_to_r2(1, 1, row);
}
 
pll getSumFrom_c1_to_c2(int parSegTree, int node, int c1, int c2, int i, int j)
{
    if (c1 > c2 || c1 > j || c2 < i) return {inf, -inf};
    if (c1 >= i && c2 <= j) return st[parSegTree][node];
    int left = node << 1;
    int right = left | 1;
    int mid = (c1 + c2) >> 1;
    pll p = getSumFrom_c1_to_c2(parSegTree, left, c1, mid, i, j);
    pll q = getSumFrom_c1_to_c2(parSegTree, right, mid + 1, c2, i, j);
    return {min(p.ff, q.ff), max(p.ss, q.ss)};
}
 
pll getSumFrom_r1_to_r2(int node, int r1, int r2, int ri, int rj, int ci, int cj)
{
    if (r1 > r2 || r1 > rj || r2 < ri) return {inf, -inf};
    if (r1 >= ri && r2 <= rj) return getSumFrom_c1_to_c2(node, 1, 1, col, ci, cj);
    int left = node << 1;
    int right = left | 1;
    int mid = (r1 + r2) >> 1;
    pll p = getSumFrom_r1_to_r2(left, r1, mid, ri, rj, ci, cj);
    pll q = getSumFrom_r1_to_r2(right, mid + 1, r2, ri, rj, ci, cj);
    return {min(p.ff, q.ff), max(p.ss, q.ss)};
}
 
pll query(int r1, int c1, int r2, int c2)
{
    return getSumFrom_r1_to_r2(1, 1, row, r1, r2, c1, c2);
}
 
void updateSegTreeIn_cx(int parSegTree, int r1, int r2, int node, int c1, int c2, int y, ll value)
{
    if (c1 > c2 || c1 > y || c2 < y) return;
    if (c1 >= y && c2 <= y)
    {
        if (r1 == r2)
        {
            st[parSegTree][node].ff = st[parSegTree][node].ss = value;
            return;
        }
        if (r1 != r2)
        {
            int leftChild = parSegTree << 1;
            int rightChild = leftChild | 1;
            st[parSegTree][node].ff = min(st[leftChild][node].ff, st[rightChild][node].ff);
            st[parSegTree][node].ss = max(st[leftChild][node].ss, st[rightChild][node].ss);
            return;
        }
    }
    int left = node << 1;
    int right = left | 1;
    int mid = (c1 + c2) >> 1;
    updateSegTreeIn_cx(parSegTree, r1, r2, left, c1, mid, y, value);
    updateSegTreeIn_cx(parSegTree, r1, r2, right, mid + 1, c2, y, value);
    st[parSegTree][node].ff = min(st[parSegTree][left].ff, st[parSegTree][right].ff);
    st[parSegTree][node].ss = max(st[parSegTree][left].ss, st[parSegTree][right].ss);
}
 
void updateSegTree(int node, int r1, int r2, int x, int y, ll value)
{
    if (r1 > r2 || r1 > x || r2 < x) return;
    if (r1 >= x && r2 <= x)
    {
        updateSegTreeIn_cx(node, r1, r2, 1, 1, col, y, value);
        return;
    }
    int left = node << 1;
    int right = left | 1;
    int mid = (r1 + r2) >> 1;
    updateSegTree(left, r1, mid, x, y, value);
    updateSegTree(right, mid+1, r2, x, y, value);
    updateSegTreeIn_cx(node, r1, r2, 1, 1, col, y, value);
}
 
void update(int x, int y, ll value)
{
    updateSegTree(1, 1, row, x, y, value);
}
 
int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
 
    scanf("%d", &row);
    col = row;
    for (int i = 1; i <= row; i++) for (int j = 1; j <= col; j++) scanf("%lld", &grid[i][j]);
    gen2DSegTree();
    int q;
    scanf("%d", &q);
    while (q--)
    {
        char type[2];
        cin >> type;
        if (type[0] == 'q')
        {
            int r1, c1, r2, c2;
            scanf("%d %d %d %d", &r1, &c1, &r2, &c2);
            pll ans = query(r1, c1, r2, c2);
            printf("%lld %lld\n", ans.ss, ans.ff);
        }
        else
        {
            int r1, c1;
            ll value;
            scanf("%d %d %lld", &r1, &c1, &value);
            update(r1, c1, value);
        }
    }
}
 

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.