Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <array>
- using namespace std;
- int preorder[200000+5];
- int father[200000+5];
- pair<long long, int> seg_tree[550000];
- pair<int, int> przedz_seg_tree[550000];
- vector<int> sasiedzi[200000+5];
- vector<int> synowie[200000+5];
- int roz[200000+5];
- int uzyteczne[200000+5];
- int n;
- int temp_preorder = 1;
- int max_pot = 1;
- long long numer_grupy=1;
- void make_Tree(int w)
- {
- int ile_sas = sasiedzi[w].size();
- for(int i=0; i<ile_sas; i++)
- {
- if(father[sasiedzi[w][i]] == 0)
- {
- father[sasiedzi[w][i]] = w;
- synowie[w].push_back(sasiedzi[w][i]);
- make_Tree(sasiedzi[w][i]);
- }
- }
- }
- void make_Preorder(int w)
- {
- preorder[w] = temp_preorder;
- temp_preorder++;
- int ile_synow = synowie[w].size();
- for(int i=0; i<ile_synow; i++)
- make_Preorder(synowie[w][i]);
- }
- void change_Add(int akt_poz, int pocz, int konc, int w_ojca, int i) ///NOWA WARTOSC JEST STALA DLA CALEGO PRZEDZIALU
- {
- ///1. JESLI PRZEDZIAL DLA WIERZCHOLKA CALKOWICIE SIE ZAWIERA
- // cout<<"JESTEM W CHANGE ADD"<<endl;
- //cout<<"akt_poz: "<<akt_poz<<" POCZ: "<<pocz<<" KONC: "<<konc<<" przedz_seg_tree[akt_poz].first: " <<przedz_seg_tree[akt_poz].first<<" przedz_seg_tree[akt_poz].second: "<<przedz_seg_tree[akt_poz].second<<endl;
- if(pocz <= przedz_seg_tree[akt_poz].first && konc >= przedz_seg_tree[akt_poz].second && i>=seg_tree[akt_poz].second)
- {
- // cout<<"PRZEDZIAL W PELNI SIE ZAWIERA W POSZUKIWANYM"<<endl;
- seg_tree[akt_poz].first = w_ojca;
- seg_tree[akt_poz].second = i;
- return;
- }
- ///2.JESLI W OGOLE NIE JEST ZAWARTE
- else if(pocz > przedz_seg_tree[akt_poz].second || konc < przedz_seg_tree[akt_poz].first)
- //{cout<<"WCALE"<<endl;
- {return;}
- ///3.JEST ZAWARTE CZESCIOWO
- else
- {
- // cout<<"CZESCIOWO"<<endl;
- change_Add(akt_poz*2, pocz, konc, w_ojca, i);
- change_Add(akt_poz*2+1, pocz, konc, w_ojca, i);
- }
- }
- void change_Divide(int akt_poz, int pocz, int konc, int i)
- {
- ///1. JESLI PRZEDZIAL DLA WIERZCHOLKA CALKOWICIE SIE ZAWIERA
- if(pocz <= przedz_seg_tree[akt_poz].first && konc >= przedz_seg_tree[akt_poz].second && seg_tree[akt_poz].second < i)
- {
- seg_tree[akt_poz].first = numer_grupy;///!!!
- seg_tree[akt_poz].second = i;
- return;
- }
- ///2.JESLI W OGOLE NIE JEST ZAWARTE
- else if(pocz > przedz_seg_tree[akt_poz].second || konc < przedz_seg_tree[akt_poz].first)
- return;
- ///3.JEST ZAWARTE CZESCIOWO
- else
- {
- change_Divide(akt_poz*2, pocz, konc, i);
- change_Divide(akt_poz*2+1, pocz, konc, i);
- }
- }
- int Find(int w)
- {
- //cout<<"FIND dla: "<<w<<endl;
- int ind = max_pot+w-1;
- ///MA ZWRACAC GRUPE DO JAKIEJ NALEZY
- //WARTOSCI POCZATKOWE:
- long long fir = seg_tree[ind].first; ///DOCELOWO GRUPA DLA NAJNIZSZEJ ZMIANY
- int sec = seg_tree[ind].second; ///DOCELOWO NAJNIZSZA ZMIANA
- do{
- ind/=2;
- if(seg_tree[ind].second > sec || fir == 0)
- {sec = seg_tree[ind].second; fir = seg_tree[ind].first;}
- }while(ind>1);
- return fir;
- }
- void Add(int i)
- {
- uzyteczne[i] = true; ///!!!
- // cout<<"DODAJE DLA WIERZCHOLKA: "<<i<<endl;
- int wartosc_ojca = Find(preorder[father[i]]);
- seg_tree[max_pot+preorder[i]-1].first = wartosc_ojca;
- seg_tree[max_pot+preorder[i]-1].second = i;
- //cout<<"POCZ ZMIAN: "<<preorder[i]<<" KONIEC: "<<preorder[i] + roz[i] - 1<<endl;
- //change_Add(1, preorder[i],preorder[i] + roz[i] - 1,wartosc_ojca, i);
- int ile_synow = synowie[i].size();
- for(int j=0; j<ile_synow; j++)
- {
- change_Add(1, preorder[synowie[i][j]],preorder[synowie[i][j]] + roz[synowie[i][j]] - 1,wartosc_ojca, i);
- }
- }
- void Divide(int i)
- {
- uzyteczne[i] = false; ///!!!
- numer_grupy++;
- seg_tree[max_pot+preorder[i]-1].first = numer_grupy;
- seg_tree[max_pot+preorder[i]-1].second = i;
- //cout<<"DZIELE DLA WIERZCHOLKA: "<<i<<endl;
- int ile_synow = synowie[i].size();
- for(int j=0; j<ile_synow; j++)
- {
- numer_grupy++;
- //cout<<"POCZ ZMIAN: "<<preorder[synowie[i][j]]<<" KONIEC: "<<preorder[synowie[i][j]]+roz[synowie[i][j]]-1<<endl;
- change_Divide(1, preorder[synowie[i][j]], preorder[synowie[i][j]]+roz[synowie[i][j]]-1, i);
- }
- }
- void Ans(int A, int B)
- {
- if(Find(preorder[A]) == Find(preorder[B]) && uzyteczne[A] == true && uzyteczne[B] == true)
- cout<<"TAK"<<endl;
- else
- cout<<"NIE"<<endl;
- }
- int make_Roz(int w)
- {
- if(roz[w] != -1)
- return roz[w];
- else
- {
- if(synowie[w].empty())
- {roz[w] = 1; return 1;}
- else
- {
- int temp=1;
- int ile_sas = synowie[w].size();
- for(int i=0; i<ile_sas; i++)
- {
- temp+=make_Roz(synowie[w][i]);
- }
- roz[w] = temp;
- return temp;
- }
- }
- }
- int main()
- {
- ios_base::sync_with_stdio(0);
- cin.tie(0);
- cin>>n;
- int t1;
- int t2;
- for(int i=1; i<n; i++)
- {
- cin>>t1;
- cin>>t2;
- sasiedzi[t1].push_back(t2);
- sasiedzi[t2].push_back(t1);
- }
- ///STWORZENIE TABLICY OJCOW I SYNOW
- father[1] = 1;
- make_Tree(1);
- /*cout<<"FATHER"<<endl;
- for(int i=1; i<=n; i++)
- cout<<i<<": "<<father[i]<<endl;*/
- for(int i=1; i<=n; i++)
- roz[i] = -1;
- make_Roz(1);
- ///STWORZENIE TABLICY PREORDER
- make_Preorder(1);
- //cout<<endl;
- //cout<<"PREORDER"<<endl;
- //for(int i=1; i<=n; i++)
- // cout<<i<<": "<<preorder[i]<<endl;
- ///STWORZENIE DRZEWA PRZEDZIALOWEGO i obliczenie ZAKRESOW dla wierzcholkow
- while(max_pot<n)
- max_pot*=2;
- //cout<<"max_pot: "<<max_pot<<endl;
- for(int i=max_pot; i<2*max_pot; i++)
- {przedz_seg_tree[i].first = i-max_pot+1;
- przedz_seg_tree[i].second = i-max_pot+1; }
- for(int i=max_pot-1; i>=1; i--)
- {
- przedz_seg_tree[i].first = przedz_seg_tree[2*i].first;
- przedz_seg_tree[i].second = przedz_seg_tree[2*i+1].second;
- }
- /*cout<<endl;
- cout<<"ZAKRESY"<<endl;
- for(int i=1; i<2*max_pot; i++)
- cout<<i<<": "<<przedz_seg_tree[i].first<<" "<<przedz_seg_tree[i].second<<endl;
- cout<<endl;
- cout<<"ROZ"<<endl;
- for(int i=1; i<2*max_pot; i++)
- cout<<i<<": "<<roz[i]<<endl;*/
- for(int i=0; i<=n; i++)
- uzyteczne[i] = true;
- int q;
- cin>>q;
- char ct1;
- int tem2;
- int t3;
- for(int i=0; i<q; i++)
- {
- cin>>ct1;
- cin>>tem2;
- if(ct1 == '?')
- {cin>>t3; Ans(tem2, t3);}
- else if(ct1 == '+')
- Add(tem2);
- else
- Divide(tem2);
- /*cout<<"DRZEWO PO ZMIANACH"<<endl;
- for(int j=1; j<2*max_pot; j++)
- cout<<j<<": "<<seg_tree[j].first<<" "<<seg_tree[j].second<<endl;
- cout<<endl;
- for(int ind=1; ind<=n; ind++)
- cout<<ind<<": "<<Find(ind)<<'\t';
- cout<<endl;*/
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement