WANNABET - Editorial

PROBLEM LINK:

Practice
Contest

Author: Siddharth
Tester: Aneesh D H , Suryansh Kumar
Editorialist: Siddharth

DIFFICULTY:

EASY

PREREQUISITES:

Trees, Ordered-Set

PROBLEM:

Given a string of lowercase alphabets we have to process 2 types of queries:
TYPE 1: Update the character at index i
TYPE 2: Print the Kth smallest alphabet in the range [L, R]

EXPLANATION:

Maintain a BIT or Segment tree for each alphabet.

  • For query of TYPE 1: We can just update the trees and replace the ith character of the string.
  • Now for query of TYPE 2: We will just calculate the number of occurrence of each alphabet in the given range [L, R] and search for the Kth smallest alphabet.

SOLUTIONS:

Setter's Solution
#include <bits/stdc++.h>
using namespace std;
string ss;
int n, q;
vector<int> FTree[30];
int getnext(int node);
int getP(int node);
void updateTree(int which, int node, int val);
void init();
void hq1(int index, int prev, int newv);
int sum(int idx,int where);
char hq2(int l,int r,int k);

int getnext(int node)
{
    return node + (node & -node);
}
int getP(int node)
{
    return node - (node & -node);
}
void updateTree(int which, int node, int val)
{
    if (node > n)
    {
        return;
    }
    FTree[which][node] += val;
    updateTree(which, getnext(node), val);
}

void init()
{
    for (int i = 0; i < 30; i++)
    {
        FTree[i].assign(n + 1, 0);
    }
    for (int i = 0; i < ss.length(); i++)
    {
        int where = ss.at(i) - 'a';
        updateTree(where, i + 1, 1);
    }
}
void hq1(int index, int prev, int newv)
{
    updateTree(prev,index,-1);
    updateTree(newv,index,1);
}
int sum(int idx,int where)
{
    if(idx<=0)
    {
        return 0;
    }
    return FTree[where][idx]+sum(getP(idx),where);
}
char hq2(int l,int r,int k)
{
    for(char c='a';c<='z';c++)
    {
        int i = c-'a';
        k-=(sum(r,i)-sum(l-1,i));
        if(k<=0)
        {
            return c;
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int t;
    cin >> t;
    while (t--)
    {
    
        cin >> n >> q >> ss;
        init();
        while (q--)
        {
            int type;
            cin >> type;
            if (type == 1)
            {
                int idx, newv, prev;
                char ch;
                cin >> idx >> ch;
                prev = ss.at(idx-1) - 'a';
                newv = ch - 'a';
                ss.at(idx-1)=ch;
                hq1(idx, prev, newv);
            }
            else
            {
                int l, r, k;
                cin >> l >> r >> k;
                cout << hq2(l,r,k)<< '\n';
            }
        }
    }
    return 0;
}
Tester's Solution
#include <bits/stdc++.h>

using namespace std;



struct BitTree{

    vector<vector<int>> bit;

    int n;

    string s;

    BitTree(string &S, int N){

        n = N;

        s = '#' + S;

        bit.assign(26 , vector<int>(n+5,0));

        for(int i=1;i<=n;i++){

            up(s[i],i,1);

        }

    }

    void up(char c,int id, int val){

        while(id<=n) bit[c - 'a'][id] += val , id += id & -id;

    }

    int sum(char c,int id){

        int ans = 0;

        while(id>0) ans+= bit[c - 'a'][id] , id -= id & -id;

        return ans;

    }

    void update(int id, char c){

        up(s[id],id,-1);

        up(c,id,1);

        s[id] = c;

    }

    char query(int l, int r, int k){

        char ans='a';

        for(char c='a';c<='z';c++){

            int temp = sum(c , r) - sum(c , l-1);

            if(temp>=k){

                ans = c;

                break;

            }

            else k -= temp;

        }

        return ans;

    }

};



void _sol(){

    int n,q; cin >> n >> q;

    string s; cin >> s;

    BitTree Tree(s,n);

    while(q--){

        int type; cin >> type;

        if(type==1){

            int id; cin >> id;

            char c; cin >> c;

            Tree.update(id,c);

        }

        else{

            int l,r,k; cin >> l >> r >> k;

            cout << Tree.query(l,r,k) << "\n";

        }

    }

    return;

}



int main() {

    #ifndef ONLINE_JUDGE

    freopen("input.txt", "r", stdin);

    freopen("output.txt", "w", stdout);

    #endif

    

    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    int t=1; cin >> t;

    while(t--) _sol();

}
4 Likes

Naive soln also passes.
here’s my solution:

void mysol()
{
    int n, q; cin >> n >> q;
    string s; cin >> s;
    s = '#' + s;
    while (q--)
    {
        int type; cin >> type;
        if (type == 1)
        {
            int a; cin >> a;
            char val ; cin >> val;
            s[a] = val;
        }
        else
        {
            int l, r, k; cin >> l >> r >> k;
            int ans[26] = {0};
            for (int i = l; i <= r; i++)
                ans[s[i] - 'a']++;
            for (int i = 0; i < 26; i++)
            {
                k -= ans[i];
                if (k <= 0) {
                    cout << char('a' + i) << endl;
                    break;
                }
            }
        }
    }
}
2 Likes

kaun sa teer mar liye bro naive solution karke. 4* ki toh laj rakh lete.

3 Likes

playing smart is the the key in CP, being oversmart and doing things which isn’t required wastes a lot of time.
So, what he did was just observe the constraints and voila! saved atleast 5-10 mins of his time.
.
I wish I had observed it to.

1 Like

Complexity is O(Q*(r-l)) ~ 10^8 operations :roll_eyes:

1 Like

Simple Inversion

Solution and explanation please :slight_smile:

1 Like

editorial will be released soon :slight_smile:

1 Like

Editorial for the problem will be out soon. Stay tuned :slight_smile:

Few hints for the Simple Inversion are:

  • Make a BIT for counting the number of inversions.
  • Then for each i in the array A :
    count the number of elements in the array A before index i that are
    greater than A[i], using BIT.
  • Then use prefix sum to solve the problem.
1 Like

Exactly. I am also surprised :sweat_smile:

I did it using ordered set and an index array in nlogn time.
Approach: We maintain inv[i] as mentioned in the problem. We start a loop in reverse order, starting from n, up to 1, find the order of it’s index in the ordered set (the number of indexes strictly smaller than the index of the current number) and update it as inv[i]. Take a cumulative sum of the newly generated array and answer query(l,r) as inv[r] - inv[l-1].

https://www.codechef.com/viewsolution/36510846

2 Likes

Wrote my solution here;

1 Like

Thanks for sharing!

First of all, he didn’t observed anything; the test cases were weak. I can easily construct test cases that satisfy those constraints and generate TLE for his code. He just didn’t know how to solve the problem, so he tried to do a brute force and expected an AC based on luck.
You on the other hand, are same as him in many ways. First you didn’t understand the problem and its constraints. Then you came here (I don’t know what is the connection between you and the writer of the solution above) and preached something about smartness in CP as if you know what is CP and what purpose does it serve.
Jaa ke phir se question padho @anonym_chef.

1 Like

Thanks for the help epsilonapha and eccentrik

1 Like