Submission #1020263

#TimeUsernameProblemLanguageResultExecution timeMemory
1020263antonParachute rings (IOI12_rings)C++17
55 / 100
4086 ms150024 KiB
#include<bits/stdc++.h> using namespace std; struct DSU{ int nbGroups =0; bool needs_op_buffer = false; vector<int> anc; vector<int> sz; vector<pair<int, pair<int, int>>> op_buffer; int nbCycles = 0; int szCycle= 0; DSU(){}; DSU(int l){ anc.resize(l); sz.resize(l); for(int i = 0; i<l; i++){ anc[i] = i; sz[i] = 1; } nbGroups = l; } int c(int u){ if(needs_op_buffer)op_buffer.push_back({u, {anc[u], sz[u]}}); if(anc[u] == u){ return u; } int v= c(anc[u]); anc[u] =v; return v; } void merge(int a, int b){ //cerr<<"merging "<<a<<" "<<b<<endl; a = c(a); b= c(b); if(a==b){ nbCycles ++; szCycle = sz[a]; return; } nbGroups--; if(needs_op_buffer)op_buffer.push_back({a, {anc[a], sz[a]}}); if(needs_op_buffer)op_buffer.push_back({b, {anc[b], sz[b]}}); if(sz[a]>sz[b]){ swap(a, b); } anc[a] = b; sz[b] += sz[a]; } void undo_op(){ auto e= op_buffer.back(); if(anc[e.first] == e.first){ nbGroups--; } op_buffer.pop_back(); anc[e.first] = e.second.first; sz[e.first] = e.second.second; if(anc[e.first] == e.first){ nbGroups++; } } void undo_buffer(){ while(op_buffer.size()>0){ undo_op(); } } }; int N; const int MAX_N= 1e6; vector<int> adj[MAX_N]; vector<int> interesting; bool isInteresting[MAX_N]; int idInteresting[MAX_N]; int deg[MAX_N], oc[MAX_N]; DSU boringDSU, fullDSU; int above3= 0; int above4=0; DSU recalcDSU(){ DSU newDSU(N); for(int iV = 0; iV<N; iV++){ for(auto u: adj[iV]){ if(!(isInteresting[u] || isInteresting[iV])){ newDSU.merge(iV, u); } } } newDSU.op_buffer.clear(); return newDSU; } int state = 0; //0 = only deg<=2 //1 only deg <=3, some interesting left //2 One deg =4, some interesting //3 no interesting left void changeDeg(int u, int d){ if(deg[u]>=3){ above3--; } if(deg[u] >= 4){ above4--; } oc[deg[u]]--; deg[u] +=d; assert(deg[u]>=0); oc[deg[u]] ++; if(deg[u]>=3){ above3++; } if(deg[u] >= 4){ above4++; } } void Init(int N_) { N = N_; fill(&oc[0], &oc[N], 0); fill(&isInteresting[0], &isInteresting[N], true); for(int i = 0; i<N; i++){ interesting.push_back(i); idInteresting[i] = i; } oc[0] =N; boringDSU = DSU(N); fullDSU = DSU(N); boringDSU.needs_op_buffer = true; } void updInteresting(int u, bool tolerant){ unordered_set<int> close; if(tolerant){ for(auto e: adj[u]){ close.insert(e); } } close.insert(u); vector<int> new_interesting; for(int i = 0; i<interesting.size(); i++){ auto it = interesting[i]; if(close.find(it) == close.end()){ isInteresting[it] = false; //cerr<<"removing "<<*it<<endl; for(auto ee: adj[it]){ if(!isInteresting[ee]){ boringDSU.merge(it, ee); } } } else{ idInteresting[it] =new_interesting.size(); new_interesting.push_back(it); } } swap(interesting, new_interesting); } void recalcDeg(){ for(int i = 0; i<N; i++){ if(deg[i] < 4){ changeDeg(i, -deg[i]); for(auto v: adj[i]){ if(deg[v] != 4){ changeDeg(i, 1); } } } } } int calcLinks(int l, int r){ int res= 0; if(l == r){ int iRem = interesting[l]; for(auto e: adj[iRem]){ changeDeg(e, -1); changeDeg(iRem, -1); } if((oc[0]-1)*2 + oc[1] == (boringDSU.nbGroups-1)*2 && above3 ==0) res= 1; for(auto e: adj[iRem]){ changeDeg(e, 1); changeDeg(iRem, 1); } return res; } int mid = (l+r)/2; int begin_size = boringDSU.op_buffer.size(); for(int i = l; i<=mid; i++){ int iAdd =interesting[i]; for(auto e: adj[iAdd]){ if((!isInteresting[e]) || !(mid+1<=idInteresting[e] && idInteresting[e]<=r)){ boringDSU.merge(e, iAdd); } } } res += calcLinks(mid+1, r); while(boringDSU.op_buffer.size()>begin_size){ boringDSU.undo_op(); } for(int i = mid+1; i<=r; i++){ int iAdd =interesting[i]; for(auto e: adj[iAdd]){ if((!isInteresting[e]) || !(l<=idInteresting[e] && idInteresting[e]<=mid)){ boringDSU.merge(e, iAdd); } } } res += calcLinks(l, mid); while(boringDSU.op_buffer.size()>begin_size){ boringDSU.undo_op(); } return res; } void Link(int A, int B) { if(interesting.size()== 0){ return; } fullDSU.merge(A, B); adj[A].push_back(B); adj[B].push_back(A); if(deg[A] <4 && deg[B] < 4){ changeDeg(A, +1); changeDeg(B, +1); } if((deg[A]== 3 || deg[B]==3)){ if(deg[A] != 3){ swap(A, B); } updInteresting(A, true); if(deg[B] == 3){ updInteresting(B, true); } } if(isInteresting[A] || isInteresting[B]){ } else{ boringDSU.merge(A, B); boringDSU.op_buffer.clear(); } if((deg[A] == 4 || deg[B]== 4) && above4 == 1){ if(deg[A] != 4){ swap(A, B); } updInteresting(A, false); if(deg[B] == 4){ updInteresting(B, false); } recalcDeg(); } } int prev_res= 0; int calc(){ if(interesting.size() == 0){ return 0; } else{ if(above4 == 1){ if((oc[0])*2 + oc[1] == (boringDSU.nbGroups-1)*2 && above3 ==1){ return 1; } return 0; } else if(above3>=1){ return calcLinks(0, interesting.size()-1); } else{ if(fullDSU.nbCycles == 0){ return N; } else if(fullDSU.nbCycles == 1){ return fullDSU.szCycle; } else{ return 0; } } } } int CountCritical() { //cerr<<oc[0]<<" "<<oc[1]<<" "<<oc[2]<<" "<<oc[3]<<endl; prev_res = calc(); return prev_res; }

Compilation message (stderr)

rings.cpp: In function 'void updInteresting(int, bool)':
rings.cpp:154:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  154 |   for(int i = 0; i<interesting.size(); i++){
      |                  ~^~~~~~~~~~~~~~~~~~~
rings.cpp: In function 'int calcLinks(int, int)':
rings.cpp:215:35: warning: comparison of integer expressions of different signedness: 'std::vector<std::pair<int, std::pair<int, int> > >::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  215 |   while(boringDSU.op_buffer.size()>begin_size){
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
rings.cpp:230:35: warning: comparison of integer expressions of different signedness: 'std::vector<std::pair<int, std::pair<int, int> > >::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  230 |   while(boringDSU.op_buffer.size()>begin_size){
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...