2019 CCF camp day 2

Heap, disjoint-set weighting disjoint-set, the split tree chain (heavy chain, long chain), lca.

stack

Single strictly O (LGN) is inserted, deleted the minimum (maximum) number, o (1) Ask the minimum (maximum) number, in practice, a point of common x * 2, x * 2 + 1, x / 2 representative of the left and right son and father.

Delete any number

In addition to the insertion / deletion top of the heap, but also to achieve the heap delete any number (to ensure that a certain heap)

With a heap to maintain the numbers need to be removed each time to see if this element is deleted when you can take the top of the heap.

Heap sort o (nlgn)

With a median inserted

Every time you insert a number, then ask all the numbers of the median

Maintaining a large and a small heap root root stack, between two piles of maintaining a difference does not exceed the number 1, o (nlgn)

K-line ordering large number of tables

There are a number of n * m table, each row of small to large numbers. The table number inquiry small number of k, required (read ignoring complexity) complexity O ((n + k) lgn).

Each taking a line from a current minimum, with a heap of maintenance at the beginning of each line, remove the current minimum deleted every time, if there are figures on this line plus inside.

K-point and small

Give you two sequences a, b, find a (x) + b (y) of k small. Requires O ((n + k) lgn)

Similar to the previous one, a (x) as a line number table, b (y) as another row number table.

t1 merger stones

Luo Valley 1090

#include <bits/stdc++.h>
using namespace std;
int n,u,ans;
priority_queue< int ,vector<int>,greater<int> >q;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)
    {    cin>>u;
        q.push(u);
    }
    while(q.size()>=2)
    {    int x=q.top();
        q.pop();
        int y=q.top();
        q.pop();
        years + = x + y; 
        q.push (x + y); 
    } 
    Cout << years;
    return  0 ; 
}
View Code

t2

White street there are n points, coordinates followed x_1 ~ x_n; personal beginning at 0. Select the i-th point blacked a_i to pay the price (we must come to this point). Finally, we must return to zero. Selecting a k th cost black point is the k and a point, the coordinates of the maximum value plus twice. For k = 1 ... n for each request, black exactly k different points of greatest price . n <= 100000

(Valley 2672 Los salesman this question, first silently cursing it, to change the title of a mess)

To come up with the case 1, case 2 can appear to, (1) 2 1 left, compared s1 + a1 + a2, (2.) In a right, compared with s2 + a1 + a2

Say

s2>s1;

It is best to choose the right; with two stacks, stacked one s * 2 + a, a put a, corresponding to the two cases, maintaining a number farthest right in the current stack, one on the left.

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;

priority_queue < pair<int,int> > q1;
priority_queue <int> q2;
struct llo{
    int s,a;
} e[100002];
int now,n,q11,q22,ans;

bool cmp(llo x,llo y){return x.s<y.s;}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)    scanf("%d",&e[i].s);
    for(int i=1;i<=n;i++)    scanf("%d",&e[i].a);
    sort(e+1,e+n+1,cmp);
    for(int i=1;i<=n;i++)    q1.push(make_pair(e[i].s*2+e[i].a,i));
    now=0;
    for(int i=1;i<=n;i++){
        q11=q22=0;
        if(!q2.empty())    q22=q2.top();
        while(!q1.empty()&&q1.top().second<=now)    q1.pop();
        if(!q1.empty())    q11=q1.top().first;
        if(q22<=q11-e[now].s*2){
            ans+=q11-e[now].s*2;
            for(int j=now+1;j<q1.top().second;j++)
                q2.push(e[j].a);
            now=q1.top().second;
            q1.pop();
        
        }
        else{
            ans+=q22;
            q2.pop();
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

Disjoint-set

Heuristic merger

Maintenance for each set a size, each element of the father on behalf of a small set of elements to representatives of a large collection of elements, so that each step jump, his son will be at least double the size of the tree, each point any time to root length of the path is O (LGN) is.

The small get big up operation is called heuristic merge.

By rank merger

Each set of maintenance maximum depth, the depth of each small hang up a large depth.

Obviously new collection depth increases 1 if and only if the original set of two equal depth, and therefore can be summed prove +1 each time the maximum depth, set size will be doubled, the complexity of the previous one

Path compression

Too simple, do not say

Complexity is based on shared equally (although some single step is costly but not total consideration), I will prove, is said to be O (n + log_ {1 + m / n} (n or m)), and in short is O (nlgn) level.

Tarjan cattle demonstrated when the compression path and by using a combined rank complexity is O (n \ alpha (n)), where \ alpha (n) is an inverse function of Ackermann, slow to grow probably you take n is the total number of atoms in the universe, this stuff probably does not exceed 6.

 

Weighting disjoint-set

Essentially focused on each point and check to father's side there is a weight, some of the information in this point to the original parent representation.

Or some of the information at this point to the parent node.

kruskal algorithm

o (mlgn) it has a very important property called circumcision nature, for a not chosen sides (called non-tree edge), will then select the edge (side of the tree) form is just a simple ring, then this non-tree edge weights given value is greater than the right side of all the trees

By means of this nature, it is assumed kruskal determined minimum spanning tree is not optimal, consider first the edge of the mistake, which corresponds to an optimal minimum spanning tree in the ring, there must be a weight ratio of its side large, so as not to meet the circumcision nature, that is, will be able to do a minimum spanning tree replacement makes this less contradictory. So kruskal is calculated minimum spanning tree. Incidentally, if the two points requires a maximum value of minimum path such that the right edge, then the use of the minimum spanning tree path a certain optimum. Because in essence, from small to big plus side to the first two connectivity is kruskal find something. It may be illustrated by circumcision properties.

Star Wars (had forgotten for hundreds of years)

#include <iostream>
#include <cstdio>
#include <vector>
#define MA 400002
using namespace std;

int n,m,a[MA],b[MA],f[MA],t,star[MA],broken[MA],iis[MA],tot;
vector <int> son[400002];

int find(int x){
    if(f[x]!=x)    f[x]=find(f[x]);
    return f[x];
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a[i],&b[i]);
        son[a[i]].push_back(b[i]);
        son[b[i]].push_back(a[i]);
    }
    for(int i=0;i<n;i++)    f[i]=i;
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        scanf("%d",&star[i]);
        broken[star[i]]=-1;
    }
    tot=n-t;
    for(int i=1;i<=m;i++){
        int x=a[i],y=b[i];
        if(broken[x]==-1||broken[y]==-1)    continue;
        else{
            int fx=find(x);
            int fy=find(y);
            if(fx!=fy){
                f[fx]=fy;
                tot--;
            }    
        }
    }
    iis[t+1]=tot;
    for(int i=t;i>=1;i--){
        //printf("%d ",broken[2]);
        tot++;
        //cout<<endl;
        broken[star[i]]=0;
        for(int j=0;j<son[star[i]].size();j++){
            int x=star[i],y=son[star[i]][j];
            if(broken[y]==-1)    continue;
            //printf("%d %d\n",x,y);
            int fx=find(x);
            int fy=find(y);
            if(fx!=fy){
                f[fy]=fx;
                tot--;
            }    
        }
        iis[i]=tot;
    }
    for(int i=1;i<=t+1;i++)
        printf("%d\n",iis[i]);
    return 0;
}
View Code

Imprisoned criminals

#include <bits/stdc++.h>
using namespace std;

struct ll{
    int mm,enemy,w;
} en[2000008];
int n,m,f[200009];

bool cmp(ll x,ll y){
    return x.w>y.w;
}

int find(int x){
    if(f[x]!=x)    f[x]=find(f[x]);
    return f[x];
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=2*n;i++)
        f[i]=i;
    for(int i=1;i<=m;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        en[i].enemy=b;
        en[i].mm=a;
        en[i].w=c;
    } 
    int ff=0;
    sort(en+1,en+m+1,cmp);
    for(int i=1;i<=m;i++){
        int x=en[i].mm,y=en[i].enemy;
        if(find(x)==find(y)||find(x+n)==find(y+n)){
            ff=en[i].w;
            break;
        }
        f[f[x]]=f[y+n];
        f[f[x+n]]=f[y];
    }
    printf("%d",ff);
    return 0;
}
View Code

tree

Storage: vector, before the chain to star

Multiplying seeking LCA

A chain associated with the conclusion:

There is a problem in some very important nature, or the intersection of the two strands of a chain, and the chain of new LCA endpoint endpoint is an article of original LCA chain.

Heavy chain and long chain split Split

Ha ha ha ha ha ha do not.

 

Guess you like

Origin www.cnblogs.com/jindui/p/11241301.html