I recently read this blog and tried to implement this data structure in problem 455D - Serega and Fun mentioned in comments but it's getting WA and I can't seem to find any bug in my data structure implementation , I know asking you all to debug my code is not good but it's a desperate move :<(
303760090 In my implementation i havn't stored size of each block as in the problem we are swapping so there's never going to be too many or too less blocks
Spoiler Code
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
#define ordered_set tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update>
#define ll long long
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define mii map<ll, ll>
#define pii pair<ll, ll>
#define vi vector<ll>
#define vvi vector<vi>
#define vb vector<bool>
#define vpii vector<pii>
#define pairMinHeap priority_queue<pii , vpii, greater<pii> >
#define all(x) (x).begin(), (x).end()
#define REP(i, a, b) for (ll i = a; i < b; i++)
#define revREP(i,a,b) for (ll i = a ; i>b ; i--)
#define MOD (ll)(1e9 + 7)
#define mod (ll)998244353
void fast()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
long long my_sqrt(long long a)
{
long long l=0,r=5000000001;
while(r-l>1)
{
long long mid=(l+r)/2;
if(1ll*mid*mid<=a)l=mid;
else r=mid;
}
return l;
}
bool cmps(pii &a, pii &b)
{
return a.ss < b.ss;
}
vector<deque<ll>> arr;
vector<map<ll,ll>> fre;
ll BLOCK_SIZE;
void shift_right(ll l)
{
if(l>=arr.size()-1)
return;
ll last_element = arr[l].back();
arr[l].pop_back();
fre[l][last_element]--;
arr[l+1].push_front(last_element);
fre[l+1][last_element]++;
shift_right(l+1);
}
void shift_left(ll l)
{
if(l>=arr.size()-1)
return;
ll first_element = arr[l+1].front();
arr[l+1].pop_front();
fre[l+1][first_element]--;
arr[l].push_back(first_element);
fre[l][first_element]++;
shift_left(l+1);
}
void insert(ll pos,ll val)
{
ll idx = pos/BLOCK_SIZE;
ll position = pos%BLOCK_SIZE;
stack<ll> s;
ll counter = position;
while(counter--)
{
s.push(arr[idx].front());
arr[idx].pop_front();
}
arr[idx].push_front(val);
fre[idx][val]++;
while(!s.empty())
{
arr[idx].push_front(s.top());
s.pop();
}
shift_right(idx);
}
ll remove(ll pos)
{
ll idx = pos/BLOCK_SIZE;
ll position = pos%BLOCK_SIZE;
stack<ll> s;
ll counter = position;
while(counter--)
{
s.push(arr[idx].front());
arr[idx].pop_front();
}
// {
ll removing_element = arr[idx].front();
arr[idx].pop_front();
fre[idx][removing_element]--;
// }
while(!s.empty())
{
arr[idx].push_front(s.top());
s.pop();
}
shift_left(idx);
return removing_element;
}
ll get_first_k(ll l,ll k)
{
ll start_idx = l/BLOCK_SIZE;
ll start_position = l%BLOCK_SIZE;
deque<ll> temp = arr[start_idx];
ll counter = start_position+1;
ll res = 0;
while(counter--)
{
if(temp.front() == k)
res++;
temp.pop_front();
}
return res;
}
ll get_last_k(ll l,ll k)
{
ll start_idx = l/BLOCK_SIZE;
ll start_position = l%BLOCK_SIZE;
deque<ll> temp = arr[start_idx];
ll counter = start_position;
ll res = 0;
while(counter--)
{
if(temp.front() == k)
res++;
temp.pop_front();
}
return fre[start_idx][k] - res;
}
void solve(ll t)
{
ll n;cin>>n;
BLOCK_SIZE = ceil(sqrt(n));
ll size = (n/BLOCK_SIZE)+1;
arr.resize(size);
fre.resize(size);
REP(i,0,n)
{
ll ele;cin>>ele;
ll idx = (i/BLOCK_SIZE);
arr[idx].push_back(ele);
fre[idx][ele]++;
}
ll last_ans = 0;
ll q;cin>>q;
REP(i,0,q)
{
ll type;cin>>type;
if(type == 1)
{
ll l,r;cin>>l>>r;
l = (l + last_ans -1 + n)%n + 1;
r = (r + last_ans -1 + n)%n + 1;
l--;
r--;
ll removed_val = remove(r);
insert(l,removed_val);
}
else
{
ll l,r,k;cin>>l>>r>>k;
l = (l + last_ans -1 + n)%n + 1;
r = (r + last_ans -1 + n)%n + 1;
l--;
r--;
if( l > r)
{
l = l^r;
r = l^r;
l = l^r;
}
k = (k + last_ans -1 + n)%n + 1;
ll end_idx = r/BLOCK_SIZE;
ll end_position = r%BLOCK_SIZE;
ll start_idx = l/BLOCK_SIZE;
ll start_position = l%BLOCK_SIZE;
if(start_idx == end_idx)
{
deque<ll> temp = arr[start_idx];
// remove first start_positon elements
ll counter = start_position;
while(counter--)
temp.pop_front();
counter = end_position - start_position + 1;
ll res = 0;
while(counter--)
{
if(temp.front() == k)
res++;
temp.pop_front();
}
last_ans = res;
cout<<res<<"\n";
}
else
{
// l -> Q(sqrt)
ll first = get_last_k(l,k);
ll second = 0;
REP(i,start_idx+1,end_idx)
{
second += fre[i][k];
}
ll third = get_first_k(r,k);
// l+1 , r-1
// r -> O(aqrt)
last_ans = first + second + third;
cout<<last_ans<<"\n";
}
}
}
return;
}
int main()
{
fast();
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
// ll t;
// cin >> t;
// REP(T,1,t+1)
{
solve(1);
cout << endl;
}
return 0;
}