0

Need help with Forest Queries II from CSES

 6 months ago
source link: https://codeforces.com/blog/entry/126821
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Hi, I tried solving Forest Queries || from CSES by building a Quaternary Segment Tree instead of a binary tree. Each child node of this tree handles on of the four quadrants. All test cases pass perfectly except for this one which gives a TLE. How can I optimize my code in order to run this testcase in under a second.

Please suggest optimizations in my code if possible. Incase there are none, how should I go about solving this question ?

My code :

/* ======================================== AKSHAT AJMERA ======================================== */
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using ull = unsigned long long;

#define fast() ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
#define loop(a,begin,end) for(__typeof(begin)a=((begin)-((begin)>(end))); a!=((end)-((begin)>(end))); a+=(1-(2*((begin)>(end)))))
#define inputVec(v) for(auto &it : v) {cin >> it;}
#define outputVec(v) for(auto &it : v) {cout << it << " ";} cout << "\n"
#ifndef ONLINE_JUDGE
    #define debug(x) cerr << '[' << #x << " is " << x << ']' << "\n"
#else
    #define debug(x)
#endif

const ull mod = 1e9+7;  // 998244353
const float PI = 3.141592653589793;
const float  E = 2.718281828459045;

// Custom Comparator
bool comp(const pair<ll,ll> &a, const pair<ll,ll> &b) {
    if(a.first != b.first) {return (a.first > b.first);}
    else {return (a.second > b.second);}
}

void buildSegTree(vector<vector<ll>> &v, vector<ll> &seg, ll top, ll bottom, ll left, ll right, ll ind) {
    if(top > bottom || left > right) return;
    if(top == bottom && left == right) {
        seg[ind] = v[top][left];
        return;
    }
    ll row_mid = (top + ((bottom - top) / 2));
    ll col_mid = (left + ((right - left) / 2));
    buildSegTree(v, seg, top, row_mid, left, col_mid, (4*ind)+1);
    buildSegTree(v, seg, row_mid+1, bottom, left, col_mid, (4*ind)+2);
    buildSegTree(v, seg, top, row_mid, col_mid+1, right, (4*ind)+3);
    buildSegTree(v, seg, row_mid+1, bottom, col_mid+1, right, (4*ind)+4);
    seg[ind] = seg[(4*ind)+1] + seg[(4*ind)+2] + seg[(4*ind)+3] + seg[(4*ind)+4];
}

void updateSegTree(vector<ll> &seg, ll top, ll bottom, ll left, ll right, ll ind, ll row, ll col) {
    if(top > bottom || left > right) return;
    if(top == bottom && left == right) {
        seg[ind] = 1 - seg[ind];
        return;
    }
    ll row_mid = (top + ((bottom - top) / 2));
    ll col_mid = (left + ((right - left) / 2));
    if(row <= row_mid && col <= col_mid) updateSegTree(seg, top, row_mid, left, col_mid, (4*ind)+1, row, col);
    else if(row > row_mid && col <= col_mid) updateSegTree(seg, row_mid+1, bottom, left, col_mid, (4*ind)+2, row, col);
    else if(row <= row_mid && col > col_mid) updateSegTree(seg, top, row_mid, col_mid+1, right, (4*ind)+3, row, col);
    else updateSegTree(seg, row_mid+1, bottom, col_mid+1, right, (4*ind)+4, row, col);
    seg[ind] = seg[(4*ind)+1] + seg[(4*ind)+2] + seg[(4*ind)+3] + seg[(4*ind)+4];
}

ll querySegTree(vector<ll> &seg, ll top, ll bottom, ll left, ll right, ll y1, ll x1, ll y2, ll x2, ll ind) {
    if((y1 > bottom) || (y2 < top) || (x1 > right) || (x2 < left) || (top > bottom) || (left > right)) return 0;
    if((y1 <= top) && (y2 >= bottom)  && (x1 <= left) && (x2 >= right)) return seg[ind];
    ll row_mid = (top + ((bottom - top) / 2));
    ll col_mid = (left + ((right - left) / 2));
    ll a = querySegTree(seg, top, row_mid, left, col_mid, y1, x1, y2, x2, (4*ind)+1);
    ll b = querySegTree(seg, row_mid+1, bottom, left, col_mid, y1, x1, y2, x2, (4*ind)+2);
    ll c = querySegTree(seg, top, row_mid, col_mid+1, right, y1, x1, y2, x2, (4*ind)+3);
    ll d = querySegTree(seg, row_mid+1, bottom, col_mid+1, right, y1, x1, y2, x2, (4*ind)+4);
    return a + b + c + d;
}

void solve() {
    ll n, q, t, y, x, y1, x1, y2, x2;
    char c;
    cin >> n >> q;
    vector<vector<ll>> v(n, vector<ll> (n, 0));
    vector<ll> seg(4*n*n, 0);
    loop(i, 0, n) {
        loop(j, 0, n) {
            cin >> c;
            if(c == '*') v[i][j] = 1;
        }
    }
    buildSegTree(v, seg, 0, n-1, 0, n-1, 0);
    while(q--) {
        cin >> t;
        if(t == 1) {
            cin >> y >> x;
            y--, x--;
            updateSegTree(seg, 0, n-1, 0, n-1, 0, y, x);
        }
        else {
            cin >> y1 >> x1 >> y2 >> x2;
            y1--, x1--, y2--, x2--;
            cout << querySegTree(seg, 0, n-1, 0, n-1, y1, x1, y2, x2, 0) << "\n";
        }
    }
    return;
}

main(void) {
    fast();
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    clock_t begin = clock();
    solve();
    clock_t end = clock();
    #ifndef ONLINE_JUDGE
        cerr << "Time Elapsed: " << (double)(end-begin)/CLOCKS_PER_SEC << " s\n";
    #endif
    return 0;
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK