Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cmath>
- #include <vector>
- #include <set>
- #include <string>
- #include <algorithm>
- using namespace std;
- using ll = long long;
- void cv(vector <ll> v){
- for (auto x: v) cout<<x<<' ';
- cout<<'\n';
- }
- ll inf = pow(2, 32);
- vector <ll> ar(1);//массив - каждый раз создается по 4-м числам
- vector <pair<ll,ll>> qr(1); //запросы - каждый раз создается по 4-м числам
- struct sct{//отрезок: левая граница включ-но, правая включ-но, min, max
- ll l, r, mn, mx;
- };
- void csc(sct f){
- cout<<f.l<<'-'<<f.r<<" ";
- }
- vector <vector <sct> > wrk; //это и есть разреж-я таблица
- vector <sct> power; //вектор для каждой степени двойки
- sct sm;//любой отрезок любой длины
- void make(){//заполнить разреженную таблицу
- int lvl = 1;//степень двойки
- int l,r;
- while (pow(2,lvl) <= ar.size()){//пока 2 в степени lvl влезает в массив ar
- vector <sct> last = wrk[wrk.size() - 1];
- //заполняем информацию об отрезках длины 2^lvl
- //с помощью информации об отрезках длины 2^(lvl-1)
- int len = pow(2, lvl);
- int hlf = len / 2;
- for (int i = 0;i<=ar.size()-len;++i){
- l = i;
- r = i + len - 1;
- sct L = last[l]; //левый отрезок длины 2^(lvl-1)
- sct R = last[l+hlf]; // правый длины 2^(lvl-1)
- sm = {l, r, min(L.mn, R.mn), max(L.mx, R.mx)};//берём минимум и максимум обоих отрезков
- power.push_back(sm);//добавляем информацию о новом отрезке в вектор, который соответствует степени двойки этого отрезка
- }
- wrk.push_back(power);
- //добавляем в разреженную таблицу вектор с информацией по отрезкам длин всех степеней двоек, которые умещаеются в массив ar
- power.clear();
- //очищаем
- lvl++;
- //увеличить степень
- }
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- ll N,M,A,B;
- while (true){
- cin>>N>>M>>A>>B;
- //cin>>N>>M>>A>>B;
- if (N==0 && M==0 && A==0 && B==0) break;
- //очистить массив чисел и запросы
- ar.clear();//массив чисел
- qr.clear();//массив запросов
- ll d;
- ll d1, d2;
- //заполняем массив чисел и массив запросов по условию
- for (int i = 1;i<=N+M*2;++i){
- if (i <= N){
- d = ( ((A % inf) * (i % inf)) % inf + (B % inf) ) % inf;
- ar.push_back(d);
- }
- else{
- d1 = ( ((A % inf) * (i % inf)) % inf + (B % inf) ) % inf % N;
- d1++;
- i++;
- d2 = ( ((A % inf) * (i % inf)) % inf + (B % inf) ) % inf % N;
- d2++;
- qr.push_back({d1, d2});
- }
- }
- //сторим разреж-ю таблицу - начиная с 2^0 - отрезков длины 1
- for (int i = 0; i < ar.size();++i){
- sm = {i, i, ar[i], ar[i]};
- power.push_back(sm);
- }
- wrk.push_back(power);
- power.clear();
- make();//создаём разреж-ю таблицу
- ll ans;
- ll tot = 0;
- //отвечаем на каждый запрос из массива запросов
- for (auto Q: qr){
- int a = min(Q.first, Q.second);
- int b = max(Q.first, Q.second);
- a--;
- b--;
- //b-a+1 = длина отрезка-запроса, включая левую и правую границы
- int LVL = floor(log(b-a+1) / log(2));//макс-я степень двойки, которая умещается в отрезок-запрос
- vector <sct> now = wrk[LVL];//вектор с информацией по всем отрезкам этой степени двойки
- sct lft = now[a];//левый отрезок длины 2^LVL
- sct rgt = now[b - pow(2,LVL) + 1];//правый отрезок длины 2^LVL
- ans = min(lft.mn, rgt.mn);//берём минимум из этих пересекающихся отрезков
- tot += ans;//прибавляем ответ
- }
- cout<<tot<<'\n';
- wrk.clear();//очищаем разреженную таблицу
- }
- }
Add Comment
Please, Sign In to add comment