Submission details
Task:Ryhmät
Sender:mangolassi
Submission time:2025-09-28 14:33:40 +0300
Language:C++ (C++11)
Status:COMPILE ERROR

Compiler report

input/code.cpp: In function 'constexpr ull intPow(ull, ull)':
input/code.cpp:22:1: error: body of 'constexpr' function 'constexpr ull intPow(ull, ull)' not a return-statement
   22 | }
      | ^
input/code.cpp: In static member function 'static constexpr int Tree<0>::nthSet(ull, int)':
input/code.cpp:136:43: error: 'popcount' was not declared in this scope; did you mean 'count'?
  136 |                                 int cou = popcount(mask & half);
      |                                           ^~~~~~~~
      |                                           count
input/code.cpp:140:46: warning: statement has no effect [-Wunused-value]
  140 |                                         mask >> len;
      |                                         ~~~~~^~~~~~
input/code.cpp:144:17: error: body of 'constexpr' function 'static constexpr int Tree<0>::nthSet(ull, int)' not a return-statement
  144 |                 }
      |                 ^
input/code.cpp: In member function 'int Tree<0>::coun...

Code

#include <bits/stdc++.h>
using namespace std;
using ull = unsigned long long;

// returns number of elements strictly smaller than v in vec
template<class T>
int bins(const vector<T>& vec, T v) {
	int low = 0;
	int high = vec.size();
	while(low != high) {
		int mid = (low + high) >> 1;
		if (vec[mid] < v) low = mid + 1;
		else high = mid;
	}
	return low;
}

constexpr ull intPow(ull a, ull b) {
	if (b == 0) return 1;
	if (b & 1) return a * intPow(a, b - 1);
	return intPow(a*a, b / 2);
}

// Persistent merge segment tree
template<int K>
struct Tree {
	private:
		using PTR_T = shared_ptr<Tree<K>>;
		using CHILD_PTR_T = shared_ptr<Tree<K-1>>;
		const static int BS = 16, BF = 10;
		const static int LEN = 64 * BS * intPow(BF, K);
		const static int CHLEN = LEN / BF;

		array<CHILD_PTR_T, BF> ch;
		int popc;
	public:
		static PTR_T zero;

		// Construction; InitTree<K>() must be called first!!
		Tree() : popc(0) {
			for (int j = 0; j < BF; ++j) ch[j] = Tree<K - 1>::zero;
		}

		int count() const { return popc; }
		void print() const { cerr << popc << ' '; ch[0]->print(); }

		// Persistent operations
		static PTR_T clonePtr(PTR_T ptr) { return make_shared<Tree<K>>(*ptr); }

		static PTR_T insert(PTR_T ptr, int x) {
			ptr = clonePtr(ptr);
			auto& obj = *ptr;

			int xj = x / CHLEN;
			obj.popc -= obj.ch[xj]->count();
			obj.ch[xj] = Tree<K-1>::insert(obj.ch[xj], x % CHLEN);
			obj.popc += obj.ch[xj]->count();

			return ptr;
		}
		static PTR_T prefixDelete(PTR_T ptr, int x) {
			ptr = clonePtr(ptr);
			auto& obj = *ptr;

			int xj = x / CHLEN;
			for (int j = 0; j < xj; ++j) {
				obj.popc -= obj.ch[j]->count();
				obj.ch[j] = Tree<K-1>::zero;
			}
			obj.popc -= obj.ch[xj]->count();
			obj.ch[xj] = Tree<K-1>::prefixDelete(obj.ch[xj], x % CHLEN);
			obj.popc += obj.ch[xj]->count();

			return ptr;
		}
		static bool countDelete(vector<PTR_T>& ptrs, const vector<int>& mults, int cou) {
			int k = ptrs.size();

			vector<int> counts(BF, 0);
			for (int i = 0; i < k; ++i) {
				for (int j = 0; j < BF; ++j) {
					counts[j] += (ptrs[i]->ch[j]->count()) * mults[i];
				}
			}
			int xj = 0;
			while(xj < BF && cou > counts[xj]) {
				cou -= counts[xj];
				++xj;
			}
			if (xj >= BF) return false; // there aren't enough elements to delete

			vector<CHILD_PTR_T> rec_ptrs(k);
			for (int i = 0; i < k; ++i) {
				ptrs[i] = clonePtr(ptrs[i]); // Make persistent copy before modifying
				auto& obj = *(ptrs[i]);
				for (int j = 0; j < xj; ++j) {
					obj.popc -= obj.ch[j]->count();
					obj.ch[j] = Tree<K-1>::zero;
				}
				obj.popc -= obj.ch[xj]->count();
				rec_ptrs[i] = obj.ch[xj];
			}

			bool sub = Tree<K-1>::countDelete(rec_ptrs, mults, cou);
			assert(sub == true);

			for (int i = 0; i < k; ++i) {
				ptrs[i]->popc += rec_ptrs[i]->count();
				ptrs[i]->ch[xj] = rec_ptrs[i];
			}
			return true;
		}
};

// Base case of the persistent sparse bitset. All operations are executed naively
template<>
struct Tree<0> {
	private:
		using PTR_T = shared_ptr<Tree<0>>;
		const static int BS = 16;
		array<ull, BS> arr;
		
		// Returns mask where bits {0, ..., x} are set and {x + 1, ..., 63} are not
		static constexpr ull prefMask(int x) {
			return (~0ull) >> (63 - (x & 63));
		}

		// Returns index of nth set bit
		// I don't think there are intrinsics to do this
		// Hopefully the compiler optimizes this for me
		static constexpr int nthSet(ull mask, int n) {
			int res = 0;
			for (int it = 0; it < 6; ++it) {
				int len = 32 >> it;
				ull half = prefMask(len - 1);
				int cou = popcount(mask & half);
				if (cou < n) {
					n -= cou;
					res += len;
					mask >> len;
				}
			}
			return res;
		}
	public:
		static PTR_T zero;

		// Construction; InitTree<0>() must be called first!!
		Tree() {
			for (int j = 0; j < BS; ++j) arr[j] = 0;	
		}

		int count() const {
			int res = 0;
			for (int j = 0; j < BS; ++j) res += popcount(arr[j]);
			return res;
		}
		void print() const {
			cerr << bitset<64>(arr[0]) << '\n';
		}
		
		// Persistent operations
		static PTR_T clonePtr(PTR_T ptr) { return make_shared<Tree<0>>(*ptr); }

		static PTR_T insert(PTR_T ptr, int x) {
			ptr = clonePtr(ptr);
			
			int xj = x / 64;
			ptr->arr[xj] |= (1ull << (x % 64));
			return ptr;
		}
		static PTR_T prefixDelete(PTR_T ptr, int x) {
			ptr = clonePtr(ptr);
			auto& arr = ptr->arr;

			int xj = x / 64;
			for (int j = 0; j < xj; ++j) arr[j] = 0;
			arr[xj] &= ~prefMask(x);
			return ptr;
		}
		static bool countDelete(vector<PTR_T>& ptrs, const vector<int>& mults, int cou) {
			int k = ptrs.size();

			array<ull, BS> comb = ptrs[0]->arr;
			for (int i = 1; i < k; ++i) {
				for (int j = 0; j < BS; ++j) comb[j] ^= ptrs[i]->arr[j];
			}
			// cerr << "countdelete with comb " << bitset<64>(comb[0]) << '\n';

			int xj = 0;
			while(xj < BS && cou > popcount(comb[xj])) {
				cou -= popcount(comb[xj]);
				++xj;
			}
			if (xj >= BS) return false;

			int x = nthSet(comb[xj], cou) + xj * 64;
			// cerr << "countdelete found bit " << x << " of " << bitset<64>(comb[0]) << '\n';
			for (int i = 0; i < k; ++i) ptrs[i] = prefixDelete(ptrs[i], x);
			return true;
		}
};

// Initialize the tree data structure
template<int K>
shared_ptr<Tree<K>> Tree<K>::zero;
shared_ptr<Tree<0>> Tree<0>::zero;

template<int K>
void initTree() {
	initTree<K-1>();
	Tree<K>::zero = make_shared<Tree<K>>();
}
template<>
void initTree<0>() {
	Tree<0>::zero = make_shared<Tree<0>>();
}

// Problem specific
const int N = 1e5;
const int THRESHOLD = 1; // 500;
int apos[N], bpos[N];
shared_ptr<Tree<2>> prefs[N + 1];

void solve(int n, const vector<pair<int, int>>& as, const vector<pair<int, int>>& bs) {
	int m;
	cin >> m;
	
	vector<int> ks(m);
	for (int& k : ks) cin >> k;
	sort(ks.begin(), ks.end());

	vector<shared_ptr<Tree<2>>> opts = {Tree<2>::zero};
	vector<int> mults = {1};

	int cur_ia = 0;
	bool works = 1;
	for (int k : ks) {
		int ia = bins(as, make_pair(k + 1, -1));
		int ib = bins(bs, make_pair(k, -1));

		// Insert new intervals
		if (ia > cur_ia) {
			int len = ia - cur_ia;
			if (len >= THRESHOLD) {
				// cerr << "Increasing " << cur_ia << ' ' << ia << '\n';
				opts.emplace_back(prefs[ia]);
				opts.emplace_back(prefs[cur_ia]);
				mults.push_back(1);
				mults.push_back(-1);
				cur_ia = ia;
			} else {
				for (; cur_ia < ia; ++cur_ia) {
					// cerr << "Inserting " << bpos[cur_ia] << '\n';
					opts[0] = Tree<2>::insert(opts[0], bpos[cur_ia]);
				}
			}
		}

		// Delete intervals that end before this
		if (ib > 0) {
			// cerr << "Clearing prefix " << ib << '\n';
			for (int i = 0; i < opts.size(); ++i) opts[i] = Tree<2>::prefixDelete(opts[i], ib - 1);
		}

		/*
		cerr << "State when handling " << k << ' ' << ia << ' ' << ib << ' ' << opts.size() << ":\n";
		for (int i = 0; i < opts.size(); ++i) {
			opts[i]->print();
		}
		*/

		// Try to fill
		works &= Tree<2>::countDelete(opts, mults, k);
		
		/*
		cerr << "State after fill:\n";
		for (int i = 0; i < opts.size(); ++i) {
			opts[i]->print();
		}
		*/
		if (! works) break;
	}

	if (! works) cout << "NO" << '\n';
	else cout << "YES" << '\n';
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int n, t;
	cin >> n >> t;
	
	vector<pair<int, int>> as(n), bs(n);
	for (int i = 0; i < n; ++i) {
		int a, b;
		cin >> a >> b;
		as[i] = {a, i};
		bs[i] = {b, i};
	}
	sort(as.begin(), as.end());
	sort(bs.begin(), bs.end());

	vector<int> ra(n);
	for (int ja = 0; ja < n; ++ja) ra[as[ja].second] = ja;
	for (int jb = 0; jb < n; ++jb) {
		int i = bs[jb].second;
		int ja = ra[i];
		apos[jb] = ja;
		bpos[ja] = jb;
	}

	initTree<2>();
	prefs[0] = Tree<2>::zero;
	for (int i = 1; i <= n; ++i) {
		prefs[i] = Tree<2>::insert(prefs[i-1], bpos[i-1]);
		// prefs[i]->print();
	}
	
	for (int ti = 0; ti < t; ++ti) solve(n, as, bs);
}