Submission #1357085

#TimeUsernameProblemLanguageResultExecution timeMemory
1357085enzySorting (IOI15_sorting)C++20
100 / 100
547 ms99812 KiB
#include "sorting.h"
#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
const int maxn=2e5+10;
int f[maxn], marc[maxn], finalizar[maxn], aa[maxn], bb[maxn], cnt, qm[maxn], tmp[maxn], qtd_ciclo, N, pai[maxn], tam[maxn];
vector<pii>seg[4*maxn];

int find(int a){
	if(pai[a]==a) return a;
	return find(pai[a]);
}

void merge(int a, int b){
	// cerr << "+ " << a << ' ' << b << '\n';
	pai[a]=b;
	tam[b]+=tam[a];
	qtd_ciclo--;
}

void roll_back(int a, int b, int ta, int tb){
	pai[a]=a; pai[b]=b;
	tam[a]=ta; tam[b]=tb;
	qtd_ciclo++;
}

void dfs(int u){
	marc[u]++;
	if(!marc[f[u]]) dfs(f[u]);
}

void get(int u){
	finalizar[u]++;
	if(!finalizar[f[u]]){
		aa[cnt]=u; bb[cnt]=f[u];
		cnt++;
		get(f[u]);
	}
}

void add(int id, int ini, int fim, int l, int r, pii p){
	if(ini>r||fim<l) return;
	if(l<=ini&&fim<=r){
		seg[id].push_back(p);
		return;
	}
	int mid=(ini+fim)/2, e=2*id, d=2*id+1;
	add(e,ini,mid,l,r,p); add(d,mid+1,fim,l,r,p);
}

void undo(stack<pair<pii,pii>>fiz){
	while(fiz.size()){
		pair<pii,pii>u=fiz.top(); fiz.pop();
		roll_back(u.fi.fi,u.fi.se,u.se.fi,u.se.se);
	}
}

int calc(int id, int ini, int fim){
	stack<pair<pii,pii>>fiz;
	for(pii p : seg[id]){
		int a=find(p.fi), b=find(p.se);
		if(a==b) continue;
		if(tam[a]>tam[b]) swap(a,b);
		fiz.push({{a,b},{tam[a],tam[b]}});
		merge(a,b);
	}
	if(ini==fim){
		// cerr << ini << ' ' << qtd_ciclo << '\n';
		int ret=maxn;
		if(N-qtd_ciclo<=ini+1) ret=ini;
		undo(fiz);
		return ret;
	}
	int mid=(ini+fim)/2, e=2*id, d=2*id+1;
	int ret=min(calc(e,ini,mid),calc(d,mid+1,fim));
	undo(fiz);
	return ret;
}

int findSwapPairs(int n, int s[], int m, int X[], int Y[], int P[], int Q[]){
	N=n;
	qtd_ciclo=n;
	for(int i=0;i<n;i++) pai[i]=i, tam[i]=1;

	int og[n], aux[n];
	for(int i=0;i<n;i++) og[s[i]]=i, aux[i]=s[i];
	// fzr a conectividade dinamica logo aaaa
	for(int i=0;i<n;i++) qm[i]=s[i];
	for(int i=0;i<n;i++){
		add(1,0,n-1,tmp[X[i]],i-1,{X[i],qm[X[i]]});
		add(1,0,n-1,tmp[Y[i]],i-1,{Y[i],qm[Y[i]]});
		swap(qm[X[i]],qm[Y[i]]);
		tmp[X[i]]=tmp[Y[i]]=i;
	}
	for(int i=0;i<n;i++) add(1,0,n-1,tmp[i],n-1,{i,qm[i]});

	cnt=0;
	auto check=[&](int z[]){
		for(int i=1;i<n;i++) if(z[i-1]>z[i]) return false;
		return true;
	};

	if(check(s)) return 0;

	auto finish=[&](int i){
		// cerr << "da pra fzr em: " << i+1 << '\n';
		// cerr << "s: ";
		// for(int j=0;j<n;j++) cerr << s[j] << ' ';
		// cerr << '\n';
		// cerr << "f: ";
		// for(int j=0;j<n;j++) cerr << f[j] << ' ';
		// cerr << '\n';
        // cerr << "og: ";
		// for(int j=0;j<n;j++) cerr << og[j] << ' ';
		// cerr << '\n';
        // cerr << "aux: ";
        // for(int j=0;j<n;j++) cerr << aux[j] << ' ';
        // cerr << '\n';
		for(int j=0;j<n;j++) if(!finalizar[j]) get(j);
		for(int j=0;j<=i;j++){
			swap(og[aux[X[j]]],og[aux[Y[j]]]);
			swap(aux[X[j]],aux[Y[j]]);
			P[j]=og[aa[j]]; Q[j]=og[bb[j]];
            // cerr << "swap " << aa[i] << ' ' << bb[j] << '\n';
			swap(og[aa[j]],og[bb[j]]);
			swap(aux[og[aa[j]]],aux[og[bb[j]]]);
            // cerr << "aux: ";
            // for(int j=0;j<n;j++) cerr << aux[j] << ' ';
            // cerr << '\n';
		}
		assert(check(aux));
		return i+1;
	}; // chamar finish(x), se tem certeza que eh possivel fzr em i passos. OBS: deixar os f's de maneira certa antes, para que o get() funcione

	int qtd=calc(1,0,n-1);
    for(int i=0;i<n;i++) s[i]=aux[i];
	for(int i=0;i<=qtd;i++) swap(s[X[i]],s[Y[i]]);
	for(int i=0;i<n;i++) f[i]=s[i];
	return finish(qtd);
}


#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...