Submission #26719

#TimeUsernameProblemLanguageResultExecution timeMemory
26719model_codeUntitled (POI11_rot)C++11
100 / 100
399 ms26824 KiB
/************************************************************************* * * * XVIII Olimpiada Informatyczna * * * * Zadanie: Rotacje na drzewie * * Autor: Adam Karczmarz * * Opis: Rozwiazanie wzorcowe * * Zlozonosc czasowa: O(n*lg^2(n)) * * * *************************************************************************/ #include <cstdio> #include <cstring> #include <algorithm> #include <cassert> #define REP(AA,BB) for(AA=0; AA<(BB); ++AA) #define FOR(AA,BB,CC) for(AA=BB; AA<(CC); ++AA) #define FC(AA,BB) for(typeof(AA.begin()) BB=AA.begin(); BB!=AA.end(); ++BB) using namespace std; // wezel drzewa struct node; struct node { node *left, *right, *prev; int sz, mn; long long inv; node() { left=right=prev=0; inv=0LL; } }; node *p[200100]; int cur, cnt[200100], MX, f; // drzewo potegowe int get(int x) { int res=0; while(x>0) { res+=cnt[x]; x-=x&(-x); } return res; } void ins(int x, int v) { while(x<=MX) { cnt[x]+=v; x+=x&(-x); } } // wczytywanie wejscia void read_input(node *tr) { int c; f=scanf("%d", &c); if(c!=0) { tr->sz=1; tr->mn=++cur; p[c-1]=tr; } else { tr->left=new node; tr->right=new node; read_input(tr->left); read_input(tr->right); tr->mn=tr->left->mn; tr->sz=tr->left->sz+tr->right->sz; } } // wstepne rotacje i liczenie dla kazdego wezla "prawego" poprzednika na sciezce do korzenia void prepare(node *tr, node *par, int x) { if(par!=0) { if(x) tr->prev=par; else tr->prev=par->prev; } if(tr->sz==1) return; if(tr->right->sz>tr->left->sz) swap(tr->left, tr->right); prepare(tr->left, tr, 0); prepare(tr->right, tr, 1); } // obliczanie wyniku przy znanej liczbie inwersji w kazdym wezle long long compute(node *tr) { if(tr->sz==1) return 0LL; return min(tr->inv, (long long)(tr->left->sz)*(tr->right->sz)-tr->inv)+compute(tr->left)+compute(tr->right); } int main(void) { int n, i; node *root=new node, *tmp; f=scanf("%d", &n); MX=n; read_input(root); prepare(root, 0, 0); FOR(i,1,n+1) ins(i,1); REP(i,n) { tmp=p[i]->prev; // aktualizacja "prawych" poprzednikow na sciezce do korzenia while(tmp!=0) { tmp->inv+=get(tmp->left->mn+tmp->left->sz-1)-get(tmp->left->mn-1); tmp=tmp->prev; } ins(p[i]->mn, -1); } printf("%lld\n", compute(root)); return 0; }
#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...
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...