[12.9] Diary

12.9 diary

Top of the heap

Function : dynamic maintenance interval k-th largest, supports insertion and deletion. Small roots heap storage of large numbers, decimals large root heap storage.

  1. P1801: Insert + k-th largest output.
#include<bits/stdc++.h>
using namespace std;
const int M=2e5+20;
int a[M];
priority_queue<int> qb;
priority_queue<int,vector<int>,greater<int> > qs;
inline void operate(int num){
    while(qb.size()<num)
        qb.push(qs.top()),qs.pop();
    while(qb.size()>num)
        qs.push(qb.top()),qb.pop();
}
inline void insert(int x){
    if (!qs.empty()&&x>qs.top())
        qs.push(x);
    else
        qb.push(x);
}
int main(){
    int m,n;
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;++i)
        scanf("%d",&a[i]);
    int q=0,p=0;
    for(int i=1;i<=n;++i){
        int ca;
        scanf("%d",&ca),++q;
        while(p<ca)
            insert(a[++p]);
        operate(q);
        printf("%d\n",qb.top());
    }
    return 0;
}

Chairman of the tree

  1. P1801:

Take the small fry cannon ......

#include<bits/stdc++.h>
using namespace std;
#define mid (l+r)/2
const int M=8e6+20,Mm=2e5+20;
int cnt,a[Mm],b[Mm],v[M],L[M],R[M],root[Mm];
unordered_map<int,int> rev;
int build(int l,int r){
    int rt=++cnt;
    v[rt]=0;
    if (l==r)
        return rt;
    build(l,mid),build(mid+1,r);
    return rt;
}
int operate(int idp,int l,int r,int pos,int x){
    int rt=++cnt;
    L[rt]=L[idp],R[rt]=R[idp],v[rt]=v[idp]+x;
    if (l==r)
        return rt;
    if (pos<=mid)
        L[rt]=operate(L[idp],l,mid,pos,x);
    else
        R[rt]=operate(R[idp],mid+1,r,pos,x);
    return rt;
}
int query(int lid,int nid,int l,int r,int k){
    if (l==r)
        return l;
    int Lnum=v[L[nid]]-v[L[lid]];
    if (Lnum>=k)
        return query(L[lid],L[nid],l,mid,k);
    else
        return query(R[lid],R[nid],mid+1,r,k-Lnum);
}
int main(){
    int m,n;
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;++i)
        scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+m+1);
    int len=unique(b+1,b+m+1)-(b+1);
    for(int i=1;i<=len;++i)
        rev[b[i]]=i;
    root[0]=build(1,len);
    int p=0;
    for(int i=1;i<=n;++i){
        int ca;
        scanf("%d",&ca);
        while(p<ca)
            root[p+1]=operate(root[p],1,len,rev[a[p+1]],1),++p;
        printf("%d\n",b[query(root[0],root[ca],1,len,i)]);
    }
    return 0;
}
  1. P3919: be persistent array

Configuration : val represents a leaf node corresponding to the target value val, other nodes useless.

Features : single point modified version of history on the basis of a single point of access to a given version value.

#include<bits/stdc++.h>
using namespace std;
#define mid (l+r)/2
const int M=3.2e7+10,Mm=1e6+10;
int cnt,root[Mm],a[Mm];
struct Tree{
    int l,r,val;
    Tree(int a=0,int b=0,int c=0):l(a),r(b),val(c){}
}v[M];
int build(int l,int r){
    int rt=++cnt;
    if (l==r){
        v[rt].val=a[l];
        return rt;
    }
    v[rt].l=build(l,mid);
    v[rt].r=build(mid+1,r);
    return rt;
}
int operate(int idp,int l,int r,int pos,int x){
    int rt=++cnt;
    v[rt]=v[idp];
    if (l==r){
        v[rt].val=x;
        return rt;
    }
    if (pos<=mid)
        v[rt].l=operate(v[idp].l,l,mid,pos,x);
    else
        v[rt].r=operate(v[idp].r,mid+1,r,pos,x);
    return rt;
}
int query(int idp,int l,int r,int pos){
    if(l==r)
        return v[idp].val;
    if(pos<=mid)
        return query(v[idp].l,l,mid,pos);
    else
        return query(v[idp].r,mid+1,r,pos);
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    root[0]=build(1,n);
    int ver=0;
    for(int i=1;i<=m;++i){
        int num,op;
        scanf("%d%d",&num,&op);
        if (op==1){
            int a,b;
            scanf("%d%d",&a,&b);
            root[++ver]=operate(root[num],1,n,a,b);
        }
        else{
            int a;
            scanf("%d",&a);
            printf("%d\n",query(root[num],1,n,a));
            root[++ver]=root[num];
        }
    }
    return 0;
}
  1. P3835: be persistent balanced tree. Each previous historical version, insert, delete (may not exist), the query x rankings (may not exist), the query ranked number x, find x precursors (may not exist), find x successor (may not exist).

Configuration : Normal range segment tree, the node number is the number of the current interval.

Note : Be sure to note that there may be no case! ! ! For now, range segment tree can do the following points

  • The number of queries value = pos There are several
  • Query values ​​<pos number a few. Two or more can be aware of the various binding <=, <,>,> =, etc. There are several numbers.
  • Who inquiry ranked as the number k yes.

If you want to maintain a maximum minimum, then it should not bother.

#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
const int M=5e5+20;
int cnt,len,rk,num;
struct Tree{
    int l,r,cnt;
    Tree(int a=0,int b=0,int c=0):l(a),r(b),cnt(c){}
}v[55*M];
int build(int l,int r){
    int rt=++cnt;
    if (l==r)
        return rt;
    v[rt].l=build(l,mid),v[rt].r=build(mid+1,r);
    return rt;
}
int query_num(int idp,int l,int r,int pos){//查询值为pos的数有几个
    if (l==r)
        return v[idp].cnt;
    if (pos<=mid)
        return query_num(v[idp].l,l,mid,pos);
    else
        return query_num(v[idp].r,mid+1,r,pos);
}
int operate(int idp,int l,int r,int pos,int x){
    int rt=++cnt;
    v[rt]=v[idp],v[rt].cnt+=x;
    if (l==r)
        return rt;
    if (pos<=mid)
        v[rt].l=operate(v[idp].l,l,mid,pos,x);
    else
        v[rt].r=operate(v[idp].r,mid+1,r,pos,x);
    return rt;
}
int query_rk(int idp,int l,int r,int pos){//查询比pos小的数有几个
    if (l==r)
        return 0;
    if (pos<=mid)
        return query_rk(v[idp].l,l,mid,pos);
    else
        return query_rk(v[idp].r,mid+1,r,pos)+v[v[idp].l].cnt;
}
int query_sa(int idp,int l,int r,int k){//查询排名为k的数
    int &Lnum=v[v[idp].l].cnt;
    if (l==r)
        return l;
    if (Lnum>=k)
        return query_sa(v[idp].l,l,mid,k);
    else
        return query_sa(v[idp].r,mid+1,r,k-Lnum);
}
struct Opt{
    int ver,op,x;
    Opt(int a=0,int b=0,int c=0):ver(a),op(b),x(c){}
}opt[M];
int lsh[M],root[M];
unordered_map<int,int> rev;
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d%d%d",&opt[i].ver,&opt[i].op,&opt[i].x),lsh[i]=opt[i].x;
    sort(lsh+1,lsh+n+1);
    len=unique(lsh+1,lsh+n+1)-(lsh+1);
    for(int i=1;i<=len;++i)
        rev[lsh[i]]=i;
    root[0]=build(1,len);
    for(int i=1;i<=n;++i)
        if (opt[i].op==1)
            root[i]=operate(root[opt[i].ver],1,len,rev[opt[i].x],1);
        else if (opt[i].op==2){
            if (query_num(root[opt[i].ver],1,len,rev[opt[i].x]))
                root[i]=operate(root[opt[i].ver],1,len,rev[opt[i].x],-1);
            else
                root[i]=root[opt[i].ver];
        }
        else if (opt[i].op==3){
            root[i]=root[opt[i].ver];
            printf("%d\n",query_rk(root[opt[i].ver],1,len,rev[opt[i].x])+1);
        }
        else if (opt[i].op==4){
            root[i]=root[opt[i].ver];
            printf("%d\n",lsh[query_sa(root[opt[i].ver],1,len,opt[i].x)]);
        }
        else if (opt[i].op==5){
            root[i]=root[opt[i].ver];
            rk=query_rk(root[opt[i].ver],1,len,rev[opt[i].x]);
            if (rk==0)
                printf("-2147483647\n");
            else
                printf("%d\n",lsh[query_sa(root[opt[i].ver],1,len,rk)]);
        }
        else if (opt[i].op==6){
            root[i]=root[opt[i].ver];
            rk=query_rk(root[opt[i].ver],1,len,rev[opt[i].x]);
            num=query_num(root[opt[i].ver],1,len,rev[opt[i].x]);
            if (rk==v[root[opt[i].ver]].cnt||(rk==v[root[opt[i].ver]].cnt-1&&num))
                printf("2147483647\n");
            else if (num)
                printf("%d\n",lsh[query_sa(root[opt[i].ver],1,len,rk+2)]);
            else
                printf("%d\n",lsh[query_sa(root[opt[i].ver],1,len,rk+1)]);
        }
    return 0;
}

Dynamic prescription segment tree

  1. P1908: the number of the reverse seek

Idea : look at there is no access to before, if not add, when asked directly if not zero.

Note :

  • cnt initialization must be 1, or on the spot explosion.
  • How much can open M opened.
#include<bits/stdc++.h>
using namespace std;
const int M=1e7+10;
#define mid ((l+r)>>1)
struct Tree{
    int l,r,val;
    Tree(int a=0,int b=0,int c=0):l(a),r(b),val(c){}
}v[M];
int cnt=1;//千万别忘了!!!
void operate(int &id,int l,int r,int pos,int x){
    if (!id)//
        id=++cnt;//
    v[id].val+=x;
    if (l==r)
        return;
    if (pos<=mid)
        operate(v[id].l,l,mid,pos,x);
    else
        operate(v[id].r,mid+1,r,pos,x);
}
int query(int id,int l,int r,int ql,int qr){
    if (!id)//
        return 0;//
    if (ql<=l&&r<=qr)
        return v[id].val;
    int sum=0;
    if (ql<=mid)
        sum+=query(v[id].l,l,mid,ql,qr);
    if (mid<qr)
        sum+=query(v[id].r,mid+1,r,ql,qr);
    return sum;
}
int main(){
    int n,root=1;
    scanf("%d",&n);
    long long ans=0;
    for(int i=1;i<=n;++i){
        int c;
        scanf("%d",&c);
        operate(root,1,1e9,c,1);
        ans+=query(1,1,1e9,c+1,1e9);
    }
    printf("%lld\n",ans);
    return 0;
}
  1. CF915E: to be completed, it is said to be dynamic prescription segment tree, lazy labeling process as follows :('m sorry I forgot which the blogger's blog ...... if infringement will be immediately deleted)
inline void pushdown(int now,int l,int r)
{
    if(lazy[now]==-1)   return;
    int k=lazy[now],m=(l+r)>>1;
 
    if(!lson[now]) lson[now]=++tot;
    sum[lson[now]]=k*(m-l+1);
    lazy[lson[now]]=lazy[now];
    
    if(!rson[now]) rson[now]=++tot;
    sum[rson[now]]=k*(r-(m+1)+1);
    lazy[rson[now]]=lazy[now];
    
    lazy[now]=-1;
}

Disjoint-set

  1. P3367: + asked whether the merger in the same collection.

Path compression is easy to understand, according to the rank of here and then look at the merger, the latter may persist disjoint-set needed. The size of each record and check the set (or is disjoint-set relationship of the tree tree height (bottom node is 1, indicating that the son of this node to find the maximum number of steps he needs to go through, or that is the deepest son) then in fact relatively simple to say that if two are used, then you can achieve linear.

#include<bits/stdc++.h>
using namespace std;
const int M=2e5+10;
int fa[M],rk[M];
int find(int x){
    return fa[x]==x?x:find(fa[x]);//return fa[x]==x?x:fa[x]=find(fa[x]);这是换成路径压缩
}
void merge(int x,int y){
    x=find(x),y=find(y);
    if (x!=y)
        if (rk[x]<=rk[y])
            fa[x]=y,rk[y]=max(rk[y],rk[x]+1);
        else
            fa[y]=x,rk[x]=max(rk[x],rk[y]+1);

}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        fa[i]=i,rk[i]=1;
    for(int i=1;i<=m;++i){
        int op,x,y;
        scanf("%d%d%d",&op,&x,&y);
        if (op==1)
            merge(x,y);
        else
            printf("%c\n",find(x)==find(y)?'Y':'N');
    }
    return 0;
}
  1. P3402: be persistent disjoint-set

Essentially the same idea, and fa is the persistence rk tree on the array may be engaged, so that each query or modify values on the array is \ (O (\ log n) \) , it is not compressed with the path (because every find is a lot of modification operations should be carried out, the data card can be constructed entirely out).

Look at some of the solution to a problem, I feel part of the algorithm can not be persisted because the time complexity is shared equally. If we add a log, it is not likely after the original complexity of shared equally so.

In short this template is very useful (feeling).

#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
const int M=2e5+20;
int cnt,root[M],n;
struct Tree{
    int l,r,fa,rk;
    Tree(int a=0,int b=0,int c=0,int d=0):l(a),r(b),fa(c),rk(d){}
}v[36*M];
int build(int l,int r){
    int rt=++cnt;
    if (l==r){
        v[rt].fa=l,v[rt].rk=1;
        return rt;
    }
    v[rt].l=build(l,mid),v[rt].r=build(mid+1,r);
    return rt;
}
int operate_rk(int idp,int l,int r,int pos,int x){
    int rt=++cnt;
    v[rt]=v[idp];
    if (l==r){
        v[rt].rk=x;
        return rt;
    }
    if (pos<=mid)
        v[rt].l=operate_rk(v[idp].l,l,mid,pos,x);
    else
        v[rt].r=operate_rk(v[idp].r,mid+1,r,pos,x);
    return rt;
}
int operate_fa(int idp,int l,int r,int pos,int x){
    int rt=++cnt;
    v[rt]=v[idp];
    if (l==r){
        v[rt].fa=x;
        return rt;
    }
    if (pos<=mid)
        v[rt].l=operate_fa(v[idp].l,l,mid,pos,x);
    else
        v[rt].r=operate_fa(v[idp].r,mid+1,r,pos,x);
    return rt;
}
Tree query(int idp,int l,int r,int pos){
    if(l==r)
        return v[idp];
    if(pos<=mid)
        return query(v[idp].l,l,mid,pos);
    else
        return query(v[idp].r,mid+1,r,pos);
}
int find(int idp,int x){
    int fax=query(idp,1,n,x).fa;
    return fax==x?x:find(idp,fax);//return fa[x]==x?x:fa[x]=find(fa[x]);这是换成路径压缩
}
int merge(int idp,int x,int y){
    x=find(idp,x),y=find(idp,y);
    if (x!=y){
        int rkx=query(idp,1,n,x).rk,rky=query(idp,1,n,y).rk;
        if (rkx<=rky)
            return operate_rk(operate_fa(idp,1,n,x,y),1,n,y,max(rky,rkx+1));
        else
            return operate_rk(operate_fa(idp,1,n,y,x),1,n,x,max(rkx,rky+1));
    }
    return idp;
}
int main(){
    int m;
    scanf("%d%d",&n,&m);
    root[0]=build(1,n);
    int now=0;
    for(int i=1;i<=m;++i){
        int op;
        scanf("%d",&op);
        if (op==2){
            int c;
            scanf("%d",&c);
            root[now+1]=root[c],++now;
        }
        else if (op==1){
            int a,b;
            scanf("%d%d",&a,&b);
            root[now+1]=merge(root[now],a,b),++now;
        }
        else{
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%d\n",find(root[now],a)==find(root[now],b)?1:0);
            root[now+1]=root[now],++now;
        }
    }
    return 0;
}

to sum up

Today wrote a lot of problems ah, a bit can be mainly whole persistent data structure, now left with the repair of the Chairman of the tree (although unrelated and Chairman of the tree) and two forced not to engage in a balanced tree.

Recently reason to feel special training course, is that he has been doing some template problems, the real upgrade should be part of the same God and qz, brush problems, mindless, but not every day and not only in learning to practice, although this practice his hand, but my mind has been the rust, natural face thinking fucks questions direct ascent.

But before the game has given us experience, if the code is not enough, even the attendance problem will not do. That's it.

So we should start even from the foundation, is to sign the title. Write, did not know how to engage in data structures, code, specifically how to achieve, what the principle is, and where you can make changes.

But, for me, if you want to dampen EC, the time is really not enough of it.

Next year it continues, can only say so, look into next year, then now everything is still very meaningful.

1 year, I do not believe not on red? Give it a try.

Impression data structure portion

In fact, the data structure is mainly on some ideas.

For example persistent data structure may be, in fact, essentially reusing existing information, and essentially no different segment tree, the structure of the written words are l, r, val. But l, r different.

Again, as far as the range of plus or minus operating, then you can consider the differential into a single operating point, and finally Fenwick tree and then merge. This 17ECFinal that J title. Do not say, the truth is too SoftBrands (pointed to himself).

Do not like to do anything can only use one as before, in fact, read so many explanations, that is not the case, mainly by thinking rather than apply (such as Chairman of the tree - small Interval k) and the like. In fact found that range segment tree can replace the basic operation of the balance of the tree, but to die in some places, such as literary balanced tree, it seems to have to use those traditional balanced tree structure to operate. Similarly, the Chairman of the tree with a repair is simply not sustainable structure of the data, but because the tree cover tree will certainly MLE, so dynamic a prescription. In essence is actually a new idea, but in time without modification, the time complexity is not good enough, there is more good chairman trees. For problems with a repair, simply can not use the Chairman of the tree, so the tree can only set the tree. So look at it, in fact, Hong Kong H is the personal questions too dishes ...... these problems if done before then, the question on H Junichi bare title.

Tomorrow Plan

  1. Dynamic prescription Fenwick tree -> tree with repair Chairman
  2. Scapegoat tree
  3. Three-dimensional scan line
  4. CDQ instead of Fenwick tree to do a single point to modify the interval sum +

Guess you like

Origin www.cnblogs.com/diorvh/p/12014406.html
Recommended