QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#825278 | #9771. Guessing Game | ucup-team112# | WA | 438ms | 98912kb | C++20 | 25.8kb | 2024-12-21 17:57:43 | 2024-12-21 17:57:49 |
Judging History
answer
//#define _GLIBCXX_DEBUG
//#pragma GCC target("avx2")
//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#include <debug_print.hpp>
#define OUT(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__)
#else
#define OUT(...) (static_cast<void>(0))
#endif
#define endl '\n'
#define lfs cout<<fixed<<setprecision(15)
#define ALL(a) (a).begin(),(a).end()
#define ALLR(a) (a).rbegin(),(a).rend()
#define UNIQUE(a) (a).erase(unique((a).begin(),(a).end()),(a).end())
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T> using PQ = priority_queue<T>;
template<typename T> using QP = priority_queue<T,vector<T>,greater<T>>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}
template<typename T1,typename T2,typename T3>void anss(T1 x,T2 y,T3 z){ans(x!=y,x,z);};
template<typename T>void debug(const T &v,ll h,ll w,string sv=" "){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout<<sv<<v[i][j];cout<<endl;}};
template<typename T>void debug(const T &v,ll n,string sv=" "){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout<<sv<<v[i];cout<<endl;};
template<typename T>void debug(const vector<T>&v){debug(v,v.size());}
template<typename T>void debug(const vector<vector<T>>&v){for(auto &vv:v)debug(vv,vv.size());}
template<typename T>void debug(stack<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(queue<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(deque<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop_front();}cout<<endl;}
template<typename T>void debug(PQ<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(QP<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(const set<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T>void debug(const multiset<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T,size_t size>void debug(const array<T, size> &a){for(auto z:a)cout<<z<<" ";cout<<endl;}
template<typename T,typename V>void debug(const map<T,V>&v){for(auto z:v)cout<<"["<<z.first<<"]="<<z.second<<",";cout<<endl;}
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << "(" << p.first << "," << p.second << ")";}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){os<<"[";for(auto &z:v)os << z << ",";os<<"]"; return os;}
template<typename T>void rearrange(vector<int>&ord, vector<T>&v){
auto tmp = v;
for(int i=0;i<tmp.size();i++)v[i] = tmp[ord[i]];
}
template<typename Head, typename... Tail>void rearrange(vector<int>&ord,Head&& head, Tail&&... tail){
rearrange(ord, head);
rearrange(ord, tail...);
}
template<typename T> vector<int> ascend(const vector<T>&v){
vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
sort(ord.begin(),ord.end(),[&](int i,int j){return make_pair(v[i],i)<make_pair(v[j],j);});
return ord;
}
template<typename T> vector<int> descend(const vector<T>&v){
vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
sort(ord.begin(),ord.end(),[&](int i,int j){return make_pair(v[i],-i)>make_pair(v[j],-j);});
return ord;
}
template<typename T> vector<T> inv_perm(const vector<T>&ord){
vector<T>inv(ord.size());
for(int i=0;i<ord.size();i++)inv[ord[i]] = i;
return inv;
}
ll FLOOR(ll n,ll div){assert(div>0);return n>=0?n/div:(n-div+1)/div;}
ll CEIL(ll n,ll div){assert(div>0);return n>=0?(n+div-1)/div:n/div;}
ll digitsum(ll n){ll ret=0;while(n){ret+=n%10;n/=10;}return ret;}
ll modulo(ll n,ll d){return (n%d+d)%d;};
template<typename T>T min(const vector<T>&v){return *min_element(v.begin(),v.end());}
template<typename T>T max(const vector<T>&v){return *max_element(v.begin(),v.end());}
template<typename T>T acc(const vector<T>&v){return accumulate(v.begin(),v.end(),T(0));};
template<typename T>T reverse(const T &v){return T(v.rbegin(),v.rend());};
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int popcount(ll x){return __builtin_popcountll(x);};
int poplow(ll x){return __builtin_ctzll(x);};
int pophigh(ll x){return 63 - __builtin_clzll(x);};
template<typename T>T poll(queue<T> &q){auto ret=q.front();q.pop();return ret;};
template<typename T>T poll(priority_queue<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(QP<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(stack<T> &s){auto ret=s.top();s.pop();return ret;};
ll MULT(ll x,ll y){if(LLONG_MAX/x<=y)return LLONG_MAX;return x*y;}
ll POW2(ll x, ll k){ll ret=1,mul=x;while(k){if(mul==LLONG_MAX)return LLONG_MAX;if(k&1)ret=MULT(ret,mul);mul=MULT(mul,mul);k>>=1;}return ret;}
ll POW(ll x, ll k){ll ret=1;for(int i=0;i<k;i++){if(LLONG_MAX/x<=ret)return LLONG_MAX;ret*=x;}return ret;}
namespace converter{
int dict[500];
const string lower="abcdefghijklmnopqrstuvwxyz";
const string upper="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string digit="0123456789";
const string digit1="123456789";
void regi_str(const string &t){
for(int i=0;i<t.size();i++){
dict[t[i]]=i;
}
}
void regi_int(const string &t){
for(int i=0;i<t.size();i++){
dict[i]=t[i];
}
}
vector<int>to_int(const string &s,const string &t){
regi_str(t);
vector<int>ret(s.size());
for(int i=0;i<s.size();i++){
ret[i]=dict[s[i]];
}
return ret;
}
vector<int>to_int(const string &s){
auto t=s;
sort(t.begin(),t.end());
t.erase(unique(t.begin(),t.end()),t.end());
return to_int(s,t);
}
vector<vector<int>>to_int(const vector<string>&s,const string &t){
regi_str(t);
vector<vector<int>>ret(s.size(),vector<int>(s[0].size()));
for(int i=0;i<s.size();i++){
for(int j=0;j<s[0].size();j++){
ret[i][j]=dict[s[i][j]];
}
}
return ret;
}
vector<vector<int>>to_int(const vector<string>&s){
string t;
for(int i=0;i<s.size();i++){
t+=s[i];
}
sort(t.begin(),t.end());t.erase(unique(t.begin(),t.end()),t.end());
return to_int(s,t);
}
string to_str(const vector<int>&s,const string &t){
regi_int(t);
string ret;
for(auto z:s)ret+=dict[z];
return ret;
}
vector<string> to_str(const vector<vector<int>>&s,const string &t){
regi_int(t);
vector<string>ret(s.size());
for(int i=0;i<s.size();i++){
for(auto z:s[i])ret[i]+=dict[z];
}
return ret;
}
}
template< typename T = int >
struct edge {
int to;
T cost;
int id;
edge():to(-1),id(-1){};
edge(int to, T cost = 1, int id = -1):to(to), cost(cost), id(id){}
operator int() const { return to; }
};
template<typename T>
using Graph = vector<vector<edge<T>>>;
template<typename T>
Graph<T>revgraph(const Graph<T> &g){
Graph<T>ret(g.size());
for(int i=0;i<g.size();i++){
for(auto e:g[i]){
int to = e.to;
e.to = i;
ret[to].push_back(e);
}
}
return ret;
}
template<typename T>
Graph<T> readGraph(int n,int m,int indexed=1,bool directed=false,bool weighted=false){
Graph<T> ret(n);
for(int es = 0; es < m; es++){
int u,v;
T w=1;
cin>>u>>v;u-=indexed,v-=indexed;
if(weighted)cin>>w;
ret[u].emplace_back(v,w,es);
if(!directed)ret[v].emplace_back(u,w,es);
}
return ret;
}
template<typename T>
Graph<T> readParent(int n,int indexed=1,bool directed=true){
Graph<T>ret(n);
for(int i=1;i<n;i++){
int p;cin>>p;
p-=indexed;
ret[p].emplace_back(i);
if(!directed)ret[i].emplace_back(p);
}
return ret;
}
template<typename T>
struct HLD{
using D=long long;
int n;
vector<int>sz;//部分木サイズ
vector<D>dep;
vector<int>par;
vector<int>head;
Graph<T> &g;//隣接リスト
vector<edge<T>>edges;//データ構造に乗せるedge列
vector<int>in,out;//[in,out)で部分木、[ina,inb]でa~bのパス(aが上)
vector<int>comp;//連結成分の根
//inは頂点のindexを表す。また、edge列の下側の頂点である
HLD(Graph<T> &g,int r=-1):g(g),n(g.size()){
hld_build(r);
}
void hld_build(int root = -1){
in.assign(n,-1);out.assign(n,-1);dep.assign(n,0);
par.assign(n,-1);head.assign(n,-1);sz.assign(n,-1);comp.assign(n,-1);
edges.assign(n,edge<T>());
if(root == -1){//根がどこでも良い場合(森でも可)
for(int i=0;i<n;i++){
if(sz[i] == -1){
head[i] = i;
dfs_sz(i, 0, i);
dfs_hld(i);
}
}
}
else{
head[root] = root;
dfs_sz(root, 0, root);
dfs_hld(root);
}
}
void dfs_sz(int k, D d,int r){
sz[k] = 1;
comp[k] = r;
dep[k] = d;
for(auto &e: g[k]){
if(e.to == par[k])continue;
par[e.to] = k;
dfs_sz(e.to, d+e.cost, r);
sz[k] += sz[e.to];
if(g[k][0].to==par[k]||sz[e.to] > sz[g[k][0].to])swap(e, g[k][0]);
}
}
int time = 0;
void dfs_hld(int k){
in[k] = time++;
for(auto e:g[k]){
if(e.to == par[k])continue;
head[e.to] = (e.to == g[k][0].to ? head[k]: e.to);
edges[time] = e;
dfs_hld(e.to);
}
out[k] = time;
}
int lca(int p,int q){
while(1){
if(in[p] < in[q])swap(p,q);
if(head[p] == head[q])return q;
p = par[head[p]];
}
}
vector<pair<int,int>>query_path(int p,int q,bool isEdge){
int r=lca(p,q);
vector<pair<int,int>>ret;
for(int i=0;i<2;i++){
if(i == 1)swap(p,q);
while(1){
if(isEdge&&p==r)break;
if(head[p]==head[r]){
ret.emplace_back(in[r]+(isEdge?1:i),in[p]+1);
break;
}
ret.emplace_back(in[head[p]],in[p]+1);
p = par[head[p]];
}
}
return ret;
}
vector<vector<pair<int,int>>>query_order_path(int p,int q,bool isEdge){
//非可換クエリ用、配列0を順番を反転したデータ構造に、配列1を通常のデータ構造に
vector<vector<pair<int,int>>>ret(2);
int r=lca(p,q);
for(int i=0;i<2;i++){
if(i == 1)swap(p,q);
while(1){
if(isEdge&&p==r)break;
if(head[p]==head[r]){
if(i==0) ret[i].emplace_back(n-(in[p]+1),n-(in[r]+(isEdge?1:i)));
else ret[i].emplace_back(in[r]+(isEdge?1:i),in[p]+1);
break;
}
if(i==0) ret[i].emplace_back(n-(in[p]+1),n-(in[head[p]]));
else ret[i].emplace_back(in[head[p]],in[p]+1);
p = par[head[p]];
}
}
reverse(ret[1].begin(), ret[1].end());
return ret;
}
pair<int,int>query_subtree(int p,bool isEdge){
return make_pair(in[p]+isEdge,out[p]);
}
//uのv方向の子 子孫関係は前もって確認すること(in,outを見る)
int child(int u,int v)const{
while(1){
if(head[u]==head[v]){
v=g[u][0].to;
break;
}
v=head[v];
if(par[v]==u)break;
v=par[v];
}
return v;
}
//uをv方向に一つ進めた頂点
int move(int u,int v)const{
assert(u!=v);
if(in[u]<in[v]&&in[v]<out[u])return child(u,v);
else return par[u];
}
D dist(int u,int v){
return dep[u]+dep[v]-2*dep[lca(u,v)];
}
vector<int>rev_in;
int climb(int u,int k){
if(rev_in.empty()){
rev_in.resize(n);
for(int i=0;i<n;i++)rev_in[in[i]]=i;
}
int nd=max<int>(dep[u]-k, 0);
while(dep[u]>nd){
if(dep[head[u]]>nd){
u=par[head[u]];
}
else{
u=rev_in[in[head[u]]+nd-dep[head[u]]];
}
}
return u;
}
int jump(int from,int to, int k){
int r = lca(from, to);
int d1 = dep[from] - dep[r];
int d2 = dep[to] - dep[r];
if(d1 + d2 < k)return -1;
else if(k <= d1)return climb(from, k);
else return climb(to, d1 + d2 - k);
}
template<typename I>
Graph<T>lca_tree(vector<I>&v){
auto compare=[&](int x,int y){return in[x]<in[y];};
sort(v.begin(),v.end(),compare);
int sz1=v.size();
for(int i=0;i<sz1-1;i++)v.push_back(lca(v[i],v[i+1]));
sort(v.begin(),v.end(),compare);
v.erase(unique(v.begin(),v.end()),v.end());
int sz2=v.size();
Graph<T>ret(sz2);
stack<int>st;
for(int i=0;i<sz2;i++){
while(!st.empty()&&out[v[st.top()]]<=in[v[i]])st.pop();
if(!st.empty()){
ret[st.top()].emplace_back(i,dep[v[i]]-dep[v[st.top()]]);
ret[i].emplace_back(st.top(),dep[v[i]]-dep[v[st.top()]]);
}
st.push(i);
}
return ret;
}
};
const int VERTEX = 0;
const int HEAVY_LIGHT = -1;
const int LIGHT = -2;
const int HEAVY = -3;
template<typename T>
struct StaticToptree{
const HLD<T> &hld;
int count;
int root;
vector<int>l,r,p;
vector<int>aff;
T edge_identity;
StaticToptree(const HLD<T> &hld):hld(hld),edge_identity(edge_identity),count(hld.n),l(hld.n*2-1,-1),r(hld.n*2-1,-1),p(hld.n*2-1,-1),aff(hld.n*2-1,VERTEX){
int hld_root=min_element(hld.in.begin(),hld.in.end())-hld.in.begin();
root = dfs(hld_root,-1).second;
}
//sz,vid
pair<int,int>dfs(int v,int par){
int sub=0;
vector<int>vs;
vector<int>sz;
int now=v,pre=par;
while(1){
int sum_sz=1;
//vid,eid
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>pq;
for(int i=1;i<hld.g[now].size();i++){
if(hld.g[now][i].to==pre)continue;
auto [sz, vid] = dfs(hld.g[now][i].to, now);
pq.emplace(sz,vid);
sum_sz+=sz;
}
sub+=sum_sz;
while(pq.size()>=2){
auto [sx,x]=pq.top();pq.pop();
auto [sy,y]=pq.top();pq.pop();
int nv=count++;
aff[nv]=LIGHT;
l[nv]=x;
p[x]=nv;
r[nv]=y;
p[y]=nv;
pq.emplace(sx+sy,nv);
}
int last=now;
if(!pq.empty()){
auto [sx,x]=pq.top();pq.pop();
int nv=count++;
aff[nv]=HEAVY_LIGHT;
l[nv]=now;
p[x]=nv;
r[nv]=x;
p[now]=nv;
last=nv;
}
vs.push_back(last);
sz.push_back(sum_sz);
if(hld.g[now].empty()||hld.g[now][0]==pre)break;
pre=now;
now=hld.g[now][0];
}
vector<int>csz(sz.size()+1);
for(int i=0;i<sz.size();i++){
csz[i+1]=csz[i]+sz[i];
}
auto rec=[&](auto &&rec,int ls,int rs)->int {
if(ls+1==rs){
return vs[ls];
}
int sum=csz[rs]-csz[ls];
int lv=-1,rv=-1;
if(sz[ls]*2>=sum){
lv=rec(rec,ls,ls+1);
rv=rec(rec,ls+1,rs);
}
else if(sz[rs-1]*2>=sum){
lv=rec(rec,ls,rs-1);
rv=rec(rec,rs-1,rs);
}
else{
int ri=min<int>(rs-1,lower_bound(csz.begin()+ls,csz.begin()+rs,csz[ls]+(sum+1)/2)-csz.begin());
int li=max(ls+1,ri-1);
if(abs((csz[li]-csz[ls])*2-sum)<abs((csz[ri]-csz[ls])*2-sum)){
ri=li;
}
lv=rec(rec,ls,ri);
rv=rec(rec,ri,rs);
}
int nv=count++;
aff[nv]=HEAVY;
l[nv]=lv,p[lv]=nv;
r[nv]=rv,p[rv]=nv;
return nv;
};
int last=rec(rec,0,sz.size());
return make_pair(sub,last);
}
};
template<typename T,typename V,typename F1,typename F2,typename F3>
struct DynamicReRooting{
const StaticToptree<T> &t;
vector<V>seg,ges;
const F1 &fh;
const F2 &fl;
const F3 &fhl;
const V M1;
vector<int>path;
DynamicReRooting(const StaticToptree<T> &t,const F1 &heavy_merge,const F2 &light_merge,const F3 &heavy_light_merge,const V M1):
t(t),fh(heavy_merge),fl(light_merge),fhl(heavy_light_merge),M1(M1){
seg.assign(t.aff.size(),M1);
ges.assign(t.aff.size(),M1);
}
void set(int k,V val){
seg[k]=val;
ges[k]=val;
}
void recalc(int k){
if(t.aff[k]==LIGHT){
seg[k]=fl(seg[t.l[k]],seg[t.r[k]]);
}
else if(t.aff[k]==HEAVY){
seg[k]=fh(seg[t.l[k]],seg[t.r[k]]);
ges[k]=fh(ges[t.r[k]],ges[t.l[k]]);
}
else if(t.aff[k]==HEAVY_LIGHT){
seg[k]=fhl(seg[t.l[k]],seg[t.r[k]]);
ges[k]=seg[k];
}
}
void build(){
for(int i=0;i<t.aff.size();i++){
recalc(i);
}
}
void update(int k,V val){
seg[k]=val;
ges[k]=val;
while(t.p[k]!=-1){
k=t.p[k];
recalc(k);
}
}
int root_path(int k){
int cnt=0;
while(1){
if(cnt>=path.size())path.push_back(0);
path[cnt++]=k;
if(t.p[k]==-1)break;
k=t.p[k];
}
return cnt;
}
//head,tail,light
tuple<V,V,V>get(int k){
int m=root_path(k);
V head=M1,tail=M1,light=M1;
int hl=-1;
for(int i=m-1;i>=1;i--){
if(t.aff[path[i]]==HEAVY){
if(t.l[path[i]]==path[i-1]){
tail=fh(seg[t.r[path[i]]],tail);
}
else{
auto lt=ges[t.l[path[i]]];
head=fh(ges[t.l[path[i]]],head);
}
}
else if(t.aff[path[i]]==HEAVY_LIGHT){
if(i==1&&k==t.l[path[i]])light=seg[t.r[path[i]]];
else hl=t.l[path[i]];
}
else{
//LIGHT
if(t.l[path[i]]==path[i-1]){
light=fl(seg[t.r[path[i]]],light);
}
else{
light=fl(seg[t.l[path[i]]],light);
}
}
if(hl!=-1&&t.aff[path[i-1]]!=LIGHT){
head=fhl(seg[hl],fl(light,fl(head,tail)));
tail=M1;
light=M1;
hl=-1;
}
}
return make_tuple(head,tail,light);
}
V reroot(int r){
auto [head,tail,light]=get(r);
return fhl(seg[r],fl(light,fl(head,tail)));
}
V reroot(int r,int k){
if(r==k)return reroot(r);
r=t.hld.move(k,r);
if(r==t.hld.par[k]){
auto [head,tail,light]=get(k);
return fhl(seg[k],fl(light,tail));
}
else{
auto [head,tail,light]=get(r);
return head;
}
}
V prod_root(){
return seg.back();
}
template<typename PF>
void print(PF printer){
vector<vector<int>>vst(t.aff.size());
for(int i=0;i<t.aff.size();i++){
if(t.aff[i]==VERTEX){
vst[i].push_back(i);
cout<<"[VERTEX]: "<<i<<endl;
}
else if(t.aff[i]==HEAVY){
vst[i]=vst[t.l[i]];
vst[i].insert(vst[i].end(),vst[t.r[i]].begin(),vst[t.r[i]].end());
cout<<"[HEAVY]: ";for(auto v:vst[i])cout<<v<<" ";cout<<endl;
}
else if(t.aff[i]==LIGHT){
for(auto v:{t.l[i],t.r[i]}){
if(t.aff[v]==LIGHT)vst[i].insert(vst[i].end(),vst[v].begin(),vst[v].end());
else vst[i].push_back(vst[v][0]);
}
cout<<"[LIGHT]: ";for(auto v:vst[i])cout<<v<<" ";cout<<endl;
}
else{
vst[i].push_back(vst[t.l[i]][0]);
cout<<"[HL]: "<<vst[i][0]<<" exclude: "<<t.hld.g[vst[i][0]][0].to<<endl;
}
printer(seg[i]);
}
}
};
struct UnionFind {
vector<ll> data;
ll num;
UnionFind(ll size) : data(size, -1) ,num(size){ }
bool unite(int x, int y) {
x = root(x); y = root(y);
if (x != y) {
if (data[y] < data[x]) swap(x, y);
data[x] += data[y]; data[y] = x;
num--;
}
return x != y;
}
bool find(int x, int y) {
return root(x) == root(y);
}
int root(int x) {
return data[x] < 0 ? x : data[x] = root(data[x]);
}
ll size(int x) {
return -data[root(x)];
}
vector<vector<int>>groups(){
vector<vector<int>>ret(data.size());
for(int i=0;i<data.size();i++){
ret[root(i)].push_back(i);
}
return ret;
}
void print(){
auto tmp=groups();
for(int i=0;i<data.size();i++){
if(!tmp[i].empty()){
for(auto z:tmp[i])cout<<z<<",";
cout<<endl;
}
}
}
};
struct FastSet{
using ull = unsigned long long;
static constexpr unsigned int B = 64;
int n,lg;
vector<vector<ull>> seg;
FastSet(int _n) : n(_n){
do{
seg.push_back(vector<ull>((_n + B - 1) / B));
_n = (_n + B - 1) / B;
} while (_n > 1);
lg = seg.size();
}
bool operator[](int i) const {
return (seg[0][i / B] >> (i % B) & 1) != 0;
}
void set(int i)
{
for(int h = 0; h < lg; h++){
seg[h][i / B] |= 1ULL << (i % B);
i /= B;
}
}
void reset(int i)
{
for(int h = 0; h < lg; h++){
seg[h][i / B] &= ~(1ULL << (i % B));
if (seg[h][i / B])
break;
i /= B;
}
}
// x以上最小の要素
int next(int i){
for(int h = 0;h < lg; h++){
if (i / B == seg[h].size())
break;
ull d = seg[h][i / B] >> (i % B);
if (!d){
i = i / B + 1;
continue;
}
// find
i += __builtin_ctzll(d);
for (int g = h - 1;g >= 0;g--){
i *= B;
i += __builtin_ctzll(seg[g][i / B]);
}
return i;
}
return n;
}
// x未満最大の要素
int prev(int i){
i--;
for (int h = 0;h < lg; h++){
if (i == -1)
break;
ull d = seg[h][i / B] << (63 - i % 64);
if (!d){
i = i / B -1;
continue;
}
// find
i += (63 - __builtin_clzll(d)) - (B - 1);
for(int g = h - 1;g >= 0;g--){
i *= B;
i += (63 - __builtin_clzll(seg[g][i / B]));
}
return i;
}
return -1;
}
};
int main(){
cin.tie(nullptr);
ios_base::sync_with_stdio(false);
ll res=0,buf=0;
bool judge = true;
int n=200010;
//cout<<"naose"<<endl;int n=6;
int off=n/2;
UnionFind uf(n);
ll q;cin>>q;
vector<ll>x(q),y(q),e(q,-1);
Graph<int>g(2*n-1);
int ei=n;
rep(i,0,q){
cin>>x[i]>>y[i];
y[i]+=off;
if(uf.unite(x[i],y[i])){
e[i]=ei++;
g[x[i]].emplace_back(e[i],1);
g[y[i]].emplace_back(e[i],1);
g[e[i]].emplace_back(x[i],1);
g[e[i]].emplace_back(y[i],1);
//OUT(x[i],y[i],e[i]);
}
}
rep(i,1,n){
if(uf.unite(0,i)){
g[0].EB(ei,1);
g[ei].EB(0,1);
g[ei].EB(i,1);
g[i].EB(ei,1);
ei++;
}
}
HLD hld(g);
StaticToptree stp(hld);
struct S{
bool cut;
int odd=0;
int sum0,sum1;
};
auto hm=[&](S h,S t){
if(h.cut)return h;
if(h.odd)swap(t.sum0,t.sum1);
auto ret=S{t.cut,h.odd^t.odd,h.sum0+t.sum0,h.sum1+t.sum1};
return ret;
};
auto lm=[&](S x,S y){
return S{false,0,x.sum0+y.sum0,x.sum1+y.sum1};
};
auto hlm=[&](S h,S t){
if(h.cut)return h;
return S{false,h.odd,h.sum0+t.sum0,h.sum1+t.sum1};
};
S iden{false,0,0,0};
DynamicReRooting seg(stp,hm,lm,hlm,iden);
rep(i,0,n)seg.set(i,S{false,0,0,0});
rep(i,n,2*n-1)seg.set(i,S{true,0,0,0});
seg.build();
uf=UnionFind(n);
vector<P>dia(n);
rep(i,0,n){
dia[i]=P(i,i);
}
FastSet fs(2*n);
rep(i,n,ei)fs.set(hld.in[i]);
auto inv=inv_perm(hld.in);
vector<P>sum(n);
P ret={0,0};
auto recalc=[&](ll pos){
pos=uf.root(pos);
sum[pos]=P(0,0);
ll l=dia[pos].fi,r=dia[pos].se;
ll diam=hld.dist(l,r);
ll ce=hld.jump(l,r,diam/2);
if(ce>=n){
if(l<off)l=hld.jump(l,r,2);
else r=hld.jump(r,l,2);
ll diam=hld.dist(l,r);
ce=hld.jump(l,r,diam/2);
sum[0].fi++;
//OUT(l,r);
}
auto tmp=seg.reroot(ce);
if(ce<off)swap(tmp.sum0,tmp.sum1);
sum[pos].fi+=tmp.sum0;
sum[pos].se+=tmp.sum1;
//OUT(ce,tmp.sum0,tmp.sum1);
};
rep(i,0,q){
if(uf.find(x[i],y[i])){
auto tmp=hld.query_path(x[i],y[i],false);
OUT(tmp);
bool ch=false;
ll pos=uf.root(x[i]);
for(auto z:tmp){
while(1){
int nxt=fs.next(z.fi);
if(nxt>=z.se)break;
fs.reset(nxt);
nxt=inv[nxt];
seg.update(nxt,S{true,0,0,0});
OUT(i,nxt);
ch=true;
}
}
if(ch){
ret.fi-=sum[pos].fi,ret.se-=sum[pos].se;
recalc(pos);
ret.fi+=sum[pos].fi,ret.se+=sum[pos].se;
}
}
else{
ll posl=uf.root(x[i]),posr=uf.root(y[i]);
ret.fi-=sum[posl].fi+sum[posr].fi,ret.se-=sum[posl].se+sum[posr].se;
ll ndl=-1,ndr=-1,ndist=-1;
for(auto lv:{dia[posl].fi,dia[posl].se}){
for(auto rv:{dia[posr].fi,dia[posr].se}){
ll dist=hld.dist(lv,rv);
if(chmax(ndist,dist)){
ndl=lv;
ndr=rv;
}
}
}
uf.unite(x[i],y[i]);
dia[uf.root(x[i])]=P(ndl,ndr);
seg.update(e[i],S{false,1,1,0});
recalc(uf.root(x[i]));
ret.fi+=sum[uf.root(x[i])].fi,ret.se+=sum[uf.root(x[i])].se;
}
// OUT(sum);
// OUT(dia);
// seg.print([&](S x){
// cout<<x.cut<<" "<<x.odd<<" "<<x.sum0<<" "<<x.sum1<<endl;
// });
cout<<ret.fi<<" "<<ret.se<<endl;
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 92ms
memory: 93148kb
input:
4 1 1 1 2 2 1 2 2
output:
1 0 0 2 1 2 0 0
result:
ok 8 numbers
Test #2:
score: -100
Wrong Answer
time: 438ms
memory: 98912kb
input:
250000 49324 49323 44443 44445 92513 92513 69591 69591 52085 52082 95024 95025 21004 21005 34373 34371 60771 60772 17131 17134 34885 34882 6011 6015 56103 56105 21055 21054 71592 71593 14894 14895 25774 25771 96225 96224 16444 16442 48432 48432 86954 86952 7202 7202 38661 38665 20063 20063 85383 853...
output:
1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 17 0 18 0 19 0 20 0 21 0 22 0 23 0 24 0 25 0 26 0 27 0 28 0 29 0 30 0 31 0 32 0 33 0 34 0 35 0 36 0 37 0 38 0 39 0 40 0 41 0 42 0 43 0 44 0 45 0 46 0 47 0 48 0 49 0 50 0 51 0 52 0 53 0 54 0 55 0 56 0 57 0 58 0 59 0 60 0 61 0 62 0...
result:
wrong answer 16437th numbers differ - expected: '7238', found: '7237'