#pragma once
template<typenameT>structSweep{usingP=pair<T,unordered_set<int>>;vector<P>basis;Sweep(){}Sweep(constvector<T>&v){for(inti=0;i<(int)v.size();i++)add(v[i],i);}// x を id と共に追加voidadd(Tx,intid){Pv{x,{id}};for(P&b:basis){if(v.first>(v.first^b.first))apply(v,b);}if(v.first!=T{})basis.push_back(v);}// pair(x を復元できるか?, {復元した時の ID の集合})pair<bool,vector<int>>restore(Tx){Pv{x,{}};for(P&b:basis){if(v.first>(v.first^b.first))apply(v,b);}if(v.first!=T{})return{false,{}};vector<int>res;for(auto&n:v.second)res.push_back(n);sort(begin(res),end(res));return{true,res};}private:voidapply(P&p,constP&o){p.first^=o.first;for(auto&x:o.second)apply(p.second,x);}voidapply(unordered_set<int>&s,intx){if(s.count(x)){s.erase(x);}else{s.insert(x);}}};/**
* @brief 掃き出し法(復元付き)
*/
#line 2 "math/sweep-restore.hpp"
template<typenameT>structSweep{usingP=pair<T,unordered_set<int>>;vector<P>basis;Sweep(){}Sweep(constvector<T>&v){for(inti=0;i<(int)v.size();i++)add(v[i],i);}// x を id と共に追加voidadd(Tx,intid){Pv{x,{id}};for(P&b:basis){if(v.first>(v.first^b.first))apply(v,b);}if(v.first!=T{})basis.push_back(v);}// pair(x を復元できるか?, {復元した時の ID の集合})pair<bool,vector<int>>restore(Tx){Pv{x,{}};for(P&b:basis){if(v.first>(v.first^b.first))apply(v,b);}if(v.first!=T{})return{false,{}};vector<int>res;for(auto&n:v.second)res.push_back(n);sort(begin(res),end(res));return{true,res};}private:voidapply(P&p,constP&o){p.first^=o.first;for(auto&x:o.second)apply(p.second,x);}voidapply(unordered_set<int>&s,intx){if(s.count(x)){s.erase(x);}else{s.insert(x);}}};/**
* @brief 掃き出し法(復元付き)
*/