Topic Description
For example, there are N small root heaps at the beginning. Each heap contains only one number. Next, two operations need to be supported:
Operation 1:1 x y merges the small root heap where the number x and y are located (ignoring this operation if the number x or Y has been deleted or the number x and y are in one heap)
Operation 2:2x outputs the minimum number of heaps where the number x is located and deletes it (output-1 ignores deletion if the number x has been deleted)
Input format
The first line contains two positive integers, N and M, representing the number of small root heaps at the beginning and the number of subsequent operations, respectively.
The second line contains N positive integers, where the first positive integer represents the number contained and contained only at the beginning of the second root heap.
Next, M lines have two or three positive integers per line, representing an operation in the following format:
Operation 1:1 x y
Operation 2:2x
Output format
The output contains several line integers corresponding to the results of each operation 2 in turn.
Input and Output Samples
Input #1 replication
5 5 1 5 4 2 3 1 1 5 1 2 5 2 2 1 4 2 2 2
Output #1 replication
1 2
Note/hint
When there are multiple minimum values in the heap, delete the front of the original sequence first, otherwise it will affect subsequent operation 1 leading to WA.
Space-time constraints: 1000ms,128M
Data size:
For 30% of the data: N<=10, M<=10
For 70% of the data: N<=1000, M<=1000
For 100% data: N <= 100000, M <= 100000
Sample description:
Initially, the five small root heaps are {1}, {5}, {4}, {2}, {3}.
In the first operation, the small root heap of the first number is merged with the small root heap of the fifth number, so it becomes four small root heaps: {1,3}, {5}, {4}, {2}.
In the second operation, the small root heap where the second number is located is merged with the small root heap where the fifth number is located, so it becomes three small root heaps: {1,3,5}, {4}, {2}.
In the third operation, the minimum value of the small root heap where the second number is located is output and deleted, so output 1, the first number is deleted, and the three small root heaps are {3,5}, {4}, {2}.
In the fourth operation, the root heap of the fourth number is merged with the root heap of the second number, so it becomes two small root heaps: {2,3,5}, {4}.
In the fifth operation, the minimum value of the small root heap where the second number is located is output and deleted, so output 2, the fourth number is deleted, and the two small root heaps are {3,5}, {4}.
So the output is 1 and 2 in turn.
The left-sided tree template problem, but the normal template will T, because a combined search is needed to speed up the query. Of course, this problem has priority_queue of pb_ds, which uses join to merge.
T Last Point
#include <bits/stdc++.h> using namespace std; typedef long long LL; /* * Merge complexity O(log N) * INIT: init()Read in the data and initialize it. * CALL: merge() Merge two left-sided trees; * ins() Insert a new node; * top() Get the smallest node; * pop() Get and delete the smallest node; * del() Delete a node; * add() Increase/decrease the key value of a node; * iroot() Get the root of node i; */ #define typec int // type of key val const int na = -1; const int N = 100010; int n,m; struct node { typec key; int l, r, f, dist; } tr[N]; int iroot(int i) { // find i's root if (i == na) { return i; } while (tr[i].f != na) { i = tr[i].f; } return i; } int merge(int rx, int ry) { // two root: rx, ry if (rx == na) { return ry; } if (ry == na) { return rx; } if (tr[rx].key > tr[ry].key) { swap(rx, ry); } int r = merge(tr[rx].r, ry); tr[rx].r = r; tr[r].f = rx; if (tr[r].dist > tr[tr[rx].l].dist) { swap(tr[rx].l, tr[rx].r); } if (tr[rx].r == na) { tr[rx].dist = 0; } else { tr[rx].dist = tr[tr[rx].r].dist + 1; } return rx; // return new root } int ins(int i, typec key, int root) { // add a new node(i, key) tr[i].key = key; tr[i].l = tr[i].r = tr[i].f = na; tr[i].dist = 0; return root = merge(root, i); // return new root } int del(int i) { // delete node i if (i == na) { return i; } int x, y, l, r; l = tr[i].l; r = tr[i].r; y = tr[i].f; tr[i].l = tr[i].r = tr[i].f = na; tr[x = merge(l, r)].f = y; if (y != na && tr[y].l == i) { tr[y].l = x; } if (y != na && tr[y].r == i) { tr[y].r = x; } for (; y != na; x = y, y = tr[y].f) { if (tr[tr[y].l].dist < tr[tr[y].r].dist) { swap(tr[y].l, tr[y].r); } if (tr[tr[y].r].dist + 1 == tr[y].dist) { break; } tr[y].dist = tr[tr[y].r].dist + 1; } if (x != na) // return new root { return iroot(x); } else return iroot(y); } node top(int root) { return tr[root]; } node pop(int &root) { node out = tr[root]; tr[root].key=-1; int l = tr[root].l, r = tr[root].r; tr[root].l = tr[root].r = tr[root].f = na; tr[l].f = tr[r].f = na; root = merge(l, r); return out; } int add(int i, typec val) // tr[i].key += val { if (i == na) { return i; } if (tr[i].l == na && tr[i].r == na && tr[i].f == na) { tr[i].key += val; return i; } typec key = tr[i].key + val; int rt = del(i); return ins(i, key, rt); } void init(int n) { for (int i = 1; i <= n; i++) { scanf("%d", &tr[i].key); // %d: type of key tr[i].l = tr[i].r = tr[i].f = na; tr[i].dist = 0; } return ; } int main() { scanf("%d%d",&n,&m); init(n); while(m--) { int op; scanf("%d",&op); if(op==1) { int x,y; scanf("%d%d",&x,&y); if(x==y) continue; if(tr[x].key==-1||tr[y].key==-1) { continue; } int fx=iroot(x),fy=iroot(y); //cout<<fx<<"*"<<fy<<endl; if(fx!=fy) merge(fx,fy); //cout<<top(fx).key<<"&"<<top(fy).key<<endl; } else { int x; scanf("%d",&x); int fx=iroot(x); if(tr[fx].key==-1) { cout<<-1<<endl; } else printf("%d\n",pop(fx).key); } } }
AC245ms
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #define MAXN 100010 using namespace std; template<class T> void swp(T &x,T &y) { T t=x; x=y; y=t; } struct node { int val;//Value represents the value of this number int ind;//index indicates that this number is the subscript in the original sequence int dis; node *lk; node *rk; int flag() { if(lk==NULL&&rk!=NULL) return 1; if(lk!=NULL&&rk!=NULL&&lk->dis<rk->dis) return 1; return 0; }//This flag is ugly, it is to judge whether the node satisfies the left-sided nature. }; node *rt[MAXN]; int n,m,f[MAXN],rnk[MAXN],used[MAXN];//f denotes the parent node of the set, rnk denotes the right to merge according to the right, and used[i] denotes whether the number I has been deleted or not. int froot(int x); int greater(node *x,node *y); int uni(int x,int y); node *merge(node *x,node *y); node *pop(node *x); node *push(node *x,int v,int i); int main() { scanf("%d %d",&n,&m); for(int i=1; i<=n; i++) rnk[i]=1; int t; for(int i=1; i<=n; i++) { scanf("%d",&t); rt[i]=push(NULL,t,i); } int flag,x,y; for(int i=1; i<=m; i++) { scanf("%d",&flag); if(flag==1) { scanf("%d %d",&x,&y); if(used[x]||used[y]) continue; int ra=froot(x),rb=froot(y); if(ra==rb) continue; int rn=uni(ra,rb); rt[rn]=merge(rt[ra],rt[rb]); } else if(flag==2) { scanf("%d",&x); if(used[x]) { puts("-1");// Remember output - 1 I wa once continue; } int ra=froot(x); printf("%d\n",rt[ra]->val); used[rt[ra]->ind]=1; rt[ra]=pop(rt[ra]); } } return 0; } int uni(int x,int y) { if(rnk[x]<rnk[y]) swp(x,y); f[y]=x; rnk[x]+=rnk[y]; return x;//Returning to the roots of a new and searched set is generic and searched not like this. } int gter(node *x,node *y) { if(x->val>y->val) return 1; if(x->val<y->val) return 0; if(x->ind>y->ind) return 1; return 0; }//Custom comparison function, because the title requires the same val ue to delete the ind smaller first, you might as well put the ind smaller on the top of the heap. int froot(int x) { if(!f[x]) return x; f[x]=froot(f[x]); return f[x]; } node *merge(node *x,node *y) { if(x==NULL) return y; if(y==NULL) return x; if(gter(x,y)) swp(x,y); x->rk=merge(x->rk,y); if(x->flag()) swp(x->lk,x->rk); x->dis=x->rk==NULL?0:x->rk->dis+1; return x; } node *pop(node *x) { node *p=x; x=merge(p->lk,p->rk); delete p; return x; } node *push(node *x,int v,int i) { node *p=new node; p->val=v; p->ind=i; p->dis=0; p->lk=NULL; p->rk=NULL; return merge(x,p); }
#include<bits/stdc++.h> #Include <bits/extc++.h>//ext Universal Header, including various ext header files using namespace std; using namespace __gnu_pbds; __gnu_pbds::priority_queue<pair<int,int>,greater<pair<int,int> >,pairing_heap_tag>h[100005]; int n,m,x,y,z,u,v,f[100005];//f is a union lookup array bool b[100005];//Is storage deleted char ch[10000009],*k=ch; pair<int,int>p; void in(int &x){ while(*k<48||*k>57)k++; for(x=*k++-48;*k>=48&&*k<=57;k++)x=(x<<1)+(x<<3)+*k-48; } int getf(int x){ return f[x]==x?x:f[x]=getf(f[x]); }//And collect int main(){ fread(ch,1,10000005,stdin); in(n),in(m); for(int i=1;i<=n;i++)in(x),f[i]=i,h[i].push(make_pair(x,i)); while(m--){ in(x); if(x==1){ in(y),in(z),u=getf(y),v=getf(z); if(b[y]||b[z]||u==v)continue;//Deleted or omitted in the same heap h[u].join(h[v]),f[v]=u; }else{ in(y),u=getf(y); if(b[y]||h[u].empty())puts("-1");//Don't forget output-1 else p=h[u].top(),h[u].pop(),b[p.second]=1,printf("%d\n",p.first); } } }