省选_简单数据结构

简单复习一下各种小模版:

其实这里的代码都是没有编译过的,时间紧迫,大概能敲下来就过了.

至于一些调试问题和语法问题就省选赛场上自由发挥了.

 

目录:

1.Link - cut - tree

2.Fenwick tree

3.静态主席树

4.动态主席树

5.Union-Find-set

6.mergable-heap

7.区间线段树

8.树链剖分

9.权值线段树的可持久化合并(CF666E)

10.权值线段树普通合并(永无乡)

11.Suffix - Automaton (EXSAM)

12.Suffix - Automaton(伪广义后缀自动机)

13.AC_Automaton 

14.KDtree

15.分块

16.非旋转treap

17.可持久treap

18.点分治

19.动态点分治

 

1. 动态树

/动态树
namespace LCT{
    int ch[maxn][2];
    int tag[maxn],lazy[maxn]; 
    int sta[maxn]; 
    int sumv[maxn]; 
    int siz[maxn]; 
    int maxv[maxn],minv[maxn]; 
    int lson(int x){ return ch[x][0]; }
    int rson(int x){ return ch[x][1]; }    
    int get(int x) { return ch[f[x]][1] == x; }
    int isRoot(int x){ return !(ch[f[x]][1]==x||ch[f[x]][0]==x); }
    void addv(int x,int delta){
        sumv[x] += siz[x] * delta; 
        lazy[x] += delta;  
    }
    void rev(int x){
        tag[x] ^= 1; 
        if(tag[x])
            swap(ch[x][0],ch[x][1]),tag[x] = 0; 
    }
    void pushdown(int x){
        if(lazy[x]) {
            addv(lson(x),lazy[x]); 
            addv(rson(x),lazy[x]); 
            lazy[x] = 0; 
        }
        if(tag[x])rev(lson(x)),rev(rson(x)),tag[x] = 0; 
    }
    void pushup(int x){
        sumv[x] = sumv[lson(x)] + sumv[rson(x)] + val[x]; 
        siz[x] = siz[lson(x)] + siz[rson(x)] + 1;         
        maxv[x] = max(maxv[lson(x)],maxv[rson(x)]); 
        minv[x] = min(minv[son(x)],minv[rson(x)]); 
    }
    void rotate(int x){
        int old=f[x],oldf=f[old],which=get(x); 
        if(!isRoot(old)) ch[oldf][ch[oldf][1]==old] = x; 
        ch[old][which]=ch[x][which^1],f[ch[old][which]]=old; 
        ch[x][which^1] = old,f[old] = x,f[x] = oldf; 
        pushup(old),pushup(x); 
    }
    void splay(int x){
        int v=0,u=x; 
        sta[++v] = x; 
        while(!isRoot(u)) sta[++v] = f[u],u=f[u]; 
        while(v) pushdown(sta[v--]); 
        u=f[u]; 
        for(int fa;(fa=f[x])!=u;rotate(x)) 
            if(f[fa]!=u) rotate(get(fa)==get(x) ? fa: x); 
    }
    void Access(int x){
        for(int y=0;x;y=x,x=f[x]) 
            splay(x),ch[x][1]=y; 
    }
    void makeRoot(int x){
        Access(x),splay(x),rev(x); 
    }
    void link(int x,int y){
        makeRoot(x),f[x]=y;
    }
    //x为y的父亲
    void cut(int x,int y){
        makeRoot(x),Access(y),splay(y); 
        ch[y][0]=f[ch[y][0]]=0; 
        pushup(y); 
    }
};

 

2. 树状数组

namespace BIT{
    int n;
    int C[maxn]; 
    int lowbit(int t) { return t & (-t); }
    void update(int x,int delta){
        while(x <= n) {
            C[x] += delta; 
            x += lowbit(x); 
        } 
    }
    int query(int x){
        int sum=0; 
        while(x >= 0)  sum += C[x],x -= lowbit(x); 
        return sum; 
    }
}; 

 

3.主席树(静态)

namespace Chair_Tree1{
    int node_cnt; 
    int ls[maxn],rs[maxn]; 
    int sumv[maxn]; 
    void build(int l,int r,int &o){
        if(l>r) return; 
        o=++node_cnt; 
        if(l==r) return ; 
        int mid=(l+r)>>1;
        build(l,mid,ls[o]); 
        build(mid+1,r,rs[o]);  
    }
    int update(int l,int r,int k,int o){
        int oo=++node_cnt; 
        sumv[oo] = sumv[o] + 1; 
        ls[oo] = ls[o];
        rs[oo] = rs[o]; 
        if(l==r) return oo; 
        int mid=(l+r)>>1;
        if(k<=mid) ls[oo] = update(l,mid,k,ls[o]); 
        else rs[oo] = update(mid+1,r,k,rs[o]); 
        return oo; 
    }
    int query(int u,int v,int l,int r,int k){
        if(l==r) return l; 
        int mid=(l+r)>>1;
        int delta = sumv[ls[v]] - sumv[ls[u]]; 
        if(delta >= k) return query(ls[u],ls[v],l,mid,k); 
        else return query(rs[u],rs[v],mid+1,r,k-delta); 
    }
};  

 

4. 主席树2(修改)

namespace Chair_Tree2{
    struct Queries{
        int c,l,r,k; 
        Queries(int c=0,int l=0,int r=0,)
    }asks[maxn]; 
    int lson[maxn*10],rson[maxn*10],root[maxn];
    int temp[2][200],count[2],sumv[maxn*10]; 
    int cnt_Tree; 
    int lowbit(int t){ return t & (-t); }       
    void insert(int l,int r,int pos,int delta,int &o){
        if(!o) o=++cnt_Tree; 
        sumv[o] += delta; 
        if(l==r) return ; 
        int mid=(l+r)>>1;
        if(pos<=mid)
            insert(l,mid,pos,delta,lson[o]); 
        else 
            insert(mid+1,r,pos,delta,rson[o]);
    }
    void update(int pos,int val,int delta){
        for(int i=pos;i<=n;i+=lowbit(i)) 
            insert(1,n,val,delta,root[i]); 
    }
    int query(int l,int r,int k){
        if(l==r) return l; 
        int sum=0; 
        for(int i=1;i<=count[0];++i) sum+=sumv[lson[temp[0][i]]];
        for(int i=1;i<=count[1];++i) sum-=sumv[lson[temp[1][i]]]; 
        int mid=(l+r)>>1;
        if(k<=sum){
            for(int i=1;i<=count[0];++i) temp[0][i]=lson[temp[0][i]]; 
            for(int i=1;i<=count[1];++i) temp[1][i]=lson[temp[1][i]]; 
            return query(l,mid,k); 
        }
        else {
            for(int i=1;i<=count[0];++i) temp[0][i]=rson[temp[0][i]];
            for(int i=1;i<=count[1];++i) temp[1][i]=rson[temp[1][i]]; 
            return query(mid+1,r,k-sum); 
        }
    }
    int Query(int l,int r,int k){
        memset(temp,0,sizeof(temp)); 
        count[0]=count[1]=0; 
        for(int i=r;i>=1;i-=lowbit(i)) 
            temp[0][++count[0]] = root[i]; 
        for(int i=l-1;i>=1;i-=lowbit(i)) 
            temp[1][++count[0]] = root[i]; 
        return query(1,n,k); 
    }
}; 

 

5.并查集

namespace Union_Find{
    int n; 
    int p[maxn]; 
    void init(){
        for(int i=1;i<=n;++i) p[i]=i;  
    }
    int find(int x){
        return p[x]==x?x:p[x] = find(p[x]); 
    }
    void merge(int a,int b){
        int x=find(a),y=find(b); 
        if(x==y) return; 
        p[x] = y; 
    }
};     

 

6.可并堆

namespace M_heap{
    int val[maxn]; 
    int ch[maxn][2]; 
    int dis[maxn]; 
    int siz[maxn]; 
    int merge(int a,int b){
        if(!a||!b) return a + b; 
        if(val[a] < val[b]) swap(a,b); 
        ch[a][1] = merge(ch[a][1],b); 
        if(dis[ch[a][1]]>dis[ch[a][0]])  swap(ch[a][0],ch[a][1]); 
        dis[a] = dis[ch[a][0]] + 1; 
        sumv[a] = sumv[ch[a][0]] + sumv[ch[a][1]] + val[a]; 
        siz[a] = siz[ch[a][0]] + siz[ch[a][1]] + 1;
        return a;  
    }
    void pop(int &a){
        int t=merge(ch[a][0],ch[a][1]); 
        siz[a] = sumv[a] = val[a] = ch[a][0] = ch[a][1] = 0; 
        a=t; 
    }
};    

 

7.线段树2(区间乘和区间加两个标记)

namespace Segment_Tree{ 
    #define ll long long  
    long long mod; 
    int val[maxn]; 
    ll sumv[maxn<<2],mult[maxn<<2],addv[maxn<<2]; 
    void pushdown(int o,int l,int r){
        int mid=(l+r)>>1,ls=(o<<1),rs=(o<<1)|1; 
        if(mult[o]!=1) {
            sumv[ls] = (sumv[ls] * mult[o])%mod;
            sumv[rs] = (sumv[rs] * mult[o])%mod; 
            mult[ls] = (mult[ls] * mult[o])%mod; 
            mult[rs] = (mult[rs] * mult[o])%mod; 
            addv[ls] = (addv[ls] * mult[o])%mod; 
            addv[rs] = (addv[rs] * mult[o])%mod; 
            mult[o] = 1; 
        }
        if(addv[o] != 0) {
            if(mid>=l) sumv[ls] += (mid-l+1) *addv[o]; 
            if(mid+1<=r) sumv[rs] += (r-mid) * addv[o]; 
            addv[ls] += addv[o],addv[rs] += addv[o]; 
            addv[o]=0; 
        }
    }
    void build_Tree(int l,int r,int o){
        if(l>r) return; 
        mult[o]=1;
        if(l==r) {
            sumv[o] = val[l]%mod; 
            return; 
        }
        int mid=(l+r)>>1,ls=(o<<1),rs=(o<<1)|1; 
        build_Tree(l,mid,ls); 
        build_Tree(mid+1,r,rs); 
        sumv[o] = (sumv[ls] + sumv[rs])%mod; 
    }
    void update_mult(int l,int r,int o,int L,int R,int delta){
        if(l > r || r < L || l > R) return; 
        if(l>=L&&r<=R) {
            sumv[o]*=delta; 
            mult[o]*=delta;
            addv[o]*=delta; 
            return; 
        }
        int mid=(l+r)>>1;
        pushdown(o,l,r); 
        update_mult(l,mid,(o<<1),L,R,delta); 
        update_mult(mid+1,r,(o<<1)|1,L,R,delta); 
        sumv[o] = sumv[(o<<1)] + sumv[(o<<1)|1]; 
    }
    void update_add(int l,int r,int o,int L,int R,int delta) {
        if(l > r || r < L || l > R) return; 
        if(l>=L&&r<=R){
            sumv[o]+=delta*(r-l+1);   
            addv[o]+=delta; 
            return; 
        }
        int mid=(l+r)>>1;
        pushdown(o,l,r); 
        update_add(l,mid,(o<<1),L,R,delta); 
        update_add(mid+1,r,(o<<1)|1,L,R,delta);
        sumv[o] = sumv[(o<<1)] + sumv[(o<<1)|1]; 
    }
    int query(int l,int r,int o,int L,int R){
        if(l > r || r < L || l > R) return 0;      
        if(l >= L && r <= R) return sumv[o]; 
        int mid=(l+r)>>1; 
        pushdown(o,l,r); 
        return query(l,mid,(o<<1),L,R)+query(mid+1,r,(o<<1)|1,L,R); 
    }
}; 

  

 8.树链剖分

namespace Heavy_Edge{
    #define ll long long 
    #define lson (o<<1)
    #define rson (o<<1)|1
    ll mod;
    int n; 
    int head[maxn],nex[maxn<<1],to[maxn<<1]; 
    int p[maxn],son[maxn],dep[maxn],top[maxn]; 
    int cnt,cnt2; 
    ll sumv[maxn<<2]; 
    int lazy[maxn];
    int A[maxn],st[maxn],ed[maxn],val[maxn]; 
    void addedge(int u,int v){
        nex[++cnt]=head[u],head[u]=cnt,to[cnt]= v;
    }
    void dfs1(int u,int fa,int cur){
        p[u]=fa,dep[u]=cur,siz[u]=1; 
        for(int i=head[u];i;i=nex[i])
            if(to[i]!=fa) {
                dfs1(to[i],u,cur+1); 
                siz[u]+=siz[to[i]]; 
                if(son[u]==-1||siz[to[i]]>siz[son[u]]) 
                    son[u] = to[i]; 
            }
        
    }
    void dfs2(int u,int tp){
        top[u]=tp,A[u]=++cnt2,st[u]=cnt2; 
        if(son[u]!=-1) dfs2(son[u],tp); 
        for(int i=head[u];i;i=nex[i])
            if(to[i]!=p[u]&&to[i]!=son[u]) 
                dfs2(to[i],to[i]); 
        ed[u]=cnt2; 
    }
    void pushdown(int l,int r,int o){
        if(lazy[o]){
            int mid=(l+r)>>1;
            lazy[lson]+=lazy[o],lazy[rson]+=lazy[o]; 
            sumv[lson]+=(mid-l+1)*lazy[o]; 
            sumv[rson]+=(r-mid)*lazy[o]; 
            lazy[o]=0; 
        }
    }
    void build(int l,int r,int o,int arr[]){
        if(l>r) return; 
        if(l==r) {
            sumv[o]=arr[l];
            return; 
        }
        int mid=(l+r)>>1;
        build(l,mid,lson,arr); 
        build(mid+1,r,rson,arr); 
        sumv[o] = sumv[lson] + sumv[rson]; 
    }
    void update(int l,int r,int k,int L,int R,int o){
        if(l>r||r<L||l>R) return;
        if(l>=L&&r<=R){
            lazy[o]+=k;
            sumv[o]+=(r-l+1)*k;
            return; 
        }
        int mid=(l+r)>>1;
        pushdown(l,r,o); 
        update(l,mid,k,L,R,lson);
        update(mid+1,r,k,L,R,rson); 
        sumv[o] = sumv[lson] + sumv[rson]; 
    }
    long long query(int l,int r,int o,int L,int R){
        if(l>r||r<L||l>R) return 0; 
        if(l>=L&&r<=R) return sumv[o]; 
        int mid=(l+r)>>1;
        pushdown(l,r,o); 
        return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R); 
    }
    void up(int x,int y,int del){
        while(top[x]!=top[y]){
            if(dep[top[x]>dep[top[y]]) swap(x,y); 
            update(1,n,del,A[top[y]],A[y],1); 
        }
        if(dep[x]<dep[y]) swap(x,y); 
        update(1,n,del,A[y],A[x],1); 
    }
    long long look_up(int x,int y){
        long long sum=0;
        while(top[x]!=top[y]) {
            if(dep[top[x]]>dep[top[y]]) swap(x,y); 
            sum+=query(1,n,1,A[top[y]],A[y]); 
            y=p[top[y]]; 
        }
        if(dep[y]>dep[x]) swap(x,y); 
        sum+=query(1,n,1,A[y],A[x];     
        return sum; 
    }
};   

 

9.权值线段树的可持久化合并(CF666E)

namespace Seg{
    struct Segment_Tree{
        int l,r,maxv; 
    }node[maxn<<2];
    int root[maxn],nodes; 
    int newnode(){ return ++nodes; }
    void update(int p,int l,int r int &o){
        if(!o) o=newnode(); 
        if(l==r){
            node[o].maxv+=1; 
            return ; 
        }
        int mid=(l+r)>>1;          
        if(p<=mid) 
            update(p,l,mid,node[o].l); 
        else 
            update(p,mid+1,r,node[o].r);
        node[o].maxv=max(node[node[o].l].maxv,node[node[o].r].maxv); 
        return o; 
    }      
    int merge(int x,int y,int l,int r){
        if(!x||!y) return x+y; 
        int o=newnode(),mid=(l+r)>>1;
        if(l==r){
            node[o].maxv=node[x].maxv+node[y].maxv; 
            return o; 
        }
        node[o].l=merge(node[x].l,node[y].l,l,mid); 
        node[o].r=merge(node[x].r,node[y].r,mid+1,r); 
        node[o].maxv=max(node[node[o].l].maxv,node[node[o].r].maxv); 
        return o; 
    }
    int query_max(int l,int r,int L,int R,int o){
        if(!o||l>r||r<L||l>R) return 0; 
        if(l>=L&&r<=R) return node[o].maxv; 
        int mid=(l+r)>>1; 
        return max(query_max(l,mid,L,R,node[o].l),query_max(mid+1,r,L,R,node[o].r)); 
    }
}; 

 

10.权值线段树普通合并(永无乡)

namespace Seg2{
    int cnt=0;
    int p[maxn],ls[maxn],rs[maxn],sumv[maxn],exe[maxn],map[maxn]; 
    int find(int x){
        return p[x] == x ? x : p[x] = find(p[x]); 
    }
    //初始化(只插入一个点QAQ) 
    void update(int l,int r,int k,int &o,int fa){
        if(!o) o=++cnt; 
        p[o]=fa;
        ++sumv[o]; 
        if(l==r) {
            exe[map[k]]=0;
            return;        
        }
        int mid=(l+r)>>1;
        if(k<=mid) 
            update(l,mid,k,ls[o],fa); 
        else 
            update(mid+1,r,k,rs[o],fa); 
    }
    int merge_tree(int x,int y){
        if(!x||!y) return x+y; 
        sumv[x] += sumv[y]; 
        ls[x] = merge(ls[x],ls[y]); 
        rs[x] = merge(rs[x],rs[y]); 
        return x; 
    }
    int query(int l,int r,int k,int o){
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(k<=sumv[ls[o]]) 
            return query(l,mid,k,ls[o]); 
        else 
            return query(mid+1,r,k-sumv[rs[o]],rs[o]); 
    }
}; 

11. Suffix - Automaton ( 真 - 广义后缀自动机)

namespace EX_SAM{
    #define maxn 1000000 
    #define digma 30 
    int ch[maxn][31],f[maxn],dis[maxn];
    int last,tot; 
    int ans; 
    void init(){ last=tot=1; }
    void ins(int c){
        if(ch[p][c]) {     
            int q=ch[p][c]; 
            if(dis[q] == dis[p] + 1) last=q; 
            else {
                int nq=++tot; last=nq; 
                dis[nq] = dis[p] + 1; 
                memcpy(ch[nq],ch[q],sizeof(ch[q])); 
                f[nq] = f[q],f[q]=nq; 
                while(p && ch[p][c] == q) ch[p][c] = nq; 
            }             
        }
        else {
            int np=++tot; p=last,last=np; dis[np] = dis[p] + 1; 
            while(p && !ch[p][c]) ch[p][c] = np,p=f[p]; 
            if(!p) 
                f[np] = 1; 
            else {
                int q=ch[p][c] 
                if(dis[q] == dis[p] + 1)    f[np] = q; 
                else {
                    int nq=++tot; 
                    dis[nq] = dis[p] + 1;
                    memcpy(ch[nq],ch[q],sizeof(ch[q])); 
                    f[nq] = f[q],f[q] = f[np] = nq;                    
                    while(p && ch[p][c] == q) ch[p][c] = nq,p=f[p]; 
                }
            }
            ans+=dis[np] - dis[f[np]]; 
        }
    }
};   

 

12.Suffix - Automaton 伪 - 广义后缀自动机

namespace SAM2{
    int ch[maxn][31],f[maxn],dis[maxn];
    int last,tot; 
    int ans; 
    void init(){ last=tot=1; }
    void ins(int c){
        int p=last,np=++tot; last=np; dis[np] = dis[p] + 1; 
        while(p && !ch[p][c]) ch[p][c] = np,p=f[p]; 
        if(!p) f[np] = 1;
        else {
            int q=ch[p][c]; 
            if(dis[q] == dis[p] + 1) f[np] = q; 
            else {
                int nq=++tot; 
                dis[nq] = dis[p] + 1;     
                memcpy(ch[nq],ch[q],sizeof(ch[q]));  
                f[nq] = f[q],f[q] = f[np] = nq; 
                while(p && ch[p][c] == q) ch[p][c] = nq, p=f[p]; 
            }
        }
        ans += dis[np] - dis[f[np]]; 
    }
};         

 

13.AC_Automaton

namespace AC_Automaton{
    #define idx str[i]-'a'
    #define root 0 
    #define sigma 27 
    int ch[maxn][sigma],last[maxn],fail[maxn],end[maxn]; 
    int nodes; 
    int newnode(){ return ++nodes; }
    void ins(char str[],int id){
        int n=strlen(str); 
        int pos = root; 
        for(int i=0;i<n;++i) {
            if(!ch[pos][idx]) 
                ch[pos][idx] = newnode(); 
            pos = ch[pos][idx]; 
        }
        G[pos].push_back(id); 
        end[pos] = 1; 
        map[id] = pos; 
    }
    queue<int>Q; 
    void build(){
        for(int i=0;i<sigma;++i) 
            if(ch[root][i]) {
                Q.push(ch[root][i]),fail[ch[root][i]]=root; 
            }
        while(!Q.empty()){
            int u = Q.front();Q.pop(); 
            for(int i=0;i<sigma;++i) {
                int r=ch[u][i]; 
                if(!r) {
                    ch[u][i]=ch[fail[u]][i]; 
                    continue; 
                }
                Q.push(r); 
                fail[r] = ch[fail[u]][i]; 
                last[t] = end[fail[r]] ? fail[r]: last[fail[r]]; 
            }    
        }
    }
    void print(int j){
        while(j) {
            if(end[j]) tag[j] += 1; 
            j = last[j]; 
        }
    }
    void query(char str[]){
        int j = root; 
        for(int i = 0;i < cnt; ++i) {
            if(str[i]=='#') j = root; 
            else {
                j = ch[j][idx]; 
                print(j); 
            }
        }
    }
}; 

 

14. KDtree(Accepted) (SJY摆棋子)

namespace KDtree{     
    int tot;
    int d; 
    int ans; 
    int n;
    int m;                             
    void init(){ tot = n, ans = inf;  }
    int newnode(){ return ++tot; }
    struct Data{
        int ch[2],minv[2],maxv[2],w,sum,p[2];      
    }node[maxn];
    bool cmp(Data i,Data j){
        return i.p[d] == j.p[d] ? i.p[d^1] < j.p[d^1]: i.p[d] < j.p[d]; 
    }
    int isin(int o,int x1,int y1,int x2,int y2){
        if(node[o].minv[0]>=x1&&node[o].maxv[0]<=x2&&node[o].minv[1]>=y1&&node[o].maxv[1]<=y2) return 1;
        return 0;  
    }
    int isout(int o,int x1,int y1,int x2,int y2){
        if(node[o].minv[0] > x2 || node[o].maxv[0] < x1) return 1; 
        if(node[o].minv[1] > y2 || node[o].maxv[1] < y1) return 1;
        return 0; 
    }
    void getmax(int &a,int b){ if( b > a ) a = b; }
    void getmin(int &a,int b){ if( b < a ) a = b; }
    void pushup(int o,int x){
        getmin(node[o].minv[0],node[x].minv[0]); 
        getmin(node[o].minv[1],node[x].minv[1]); 
        getmax(node[o].maxv[1],node[x].maxv[1]); 
        getmax(node[o].maxv[0],node[x].maxv[0]); 
        node[o].sum += node[x].sum; 
    }
    int build(int l,int r,int o){
        int mid = (l + r) >> 1;              
        d = o ; nth_element(node+l,node+mid,node+r+1,cmp); 
        node[mid].minv[0] = node[mid].maxv[0] = node[mid].p[0]; 
        node[mid].minv[1] = node[mid].maxv[1] = node[mid].p[1]; 
        node[mid].sum = node[mid].w; 
        node[mid].ch[0] = node[mid].ch[1] = 0; 
        if(l < mid) node[mid].ch[0] = build(l,mid - 1,o ^ 1), pushup(mid,node[mid].ch[0]); 
        if(r > mid) node[mid].ch[1] = build(mid + 1, r, o ^ 1), pushup(mid,node[mid].ch[1]); 
        return mid; 
    }
    void update(int &o,Data x,int de){
        if(!o) {
            o = newnode();  
            node[o].p[0] = node[o].maxv[0] = node[o].minv[0] = x.p[0]; 
            node[o].p[1] = node[o].minv[1] = node[o].maxv[1] = x.p[1]; 
            return; 
        }
        if(x.p[de] < node[o].p[de]) update(node[o].ch[0],x,de^1),pushup(o,node[o].ch[0]); 
        else update(node[o].ch[1],x,de^1),pushup(o,node[o].ch[1]); 
    }
    int getdis(int o,int x1,int y1){
        int dis = 0;
        if(x1 < node[o].minv[0]) dis += node[o].minv[0] - x1;
        if(x1 > node[o].maxv[0]) dis += x1 - node[o].maxv[0]; 
        if(y1 < node[o].minv[1]) dis += node[o].minv[1] - y1; 
        if(y1 > node[o].maxv[1]) dis += y1 - node[o].maxv[1]; 
        return dis; 
    }
    void query(int o,int x1,int y1){
        int dn = abs(node[o].p[0] - x1) + abs(node[o].p[1] - y1),dl,dr; 
        ans = min(ans,dn); 
        dl = node[o].ch[0] ? getdis(node[o].ch[0],x1,y1) : inf; 
        dr = node[o].ch[1] ? getdis(node[o].ch[1],x1,y1) : inf; 
        if(dl < dr) {
            if(dl < ans) query(node[o].ch[0],x1,y1); 
            if(dr < ans) query(node[o].ch[1],x1,y1);             
        }
        else {
            if(dr < ans) query(node[o].ch[1],x1,y1); 
            if(dl < ans) query(node[o].ch[0],x1,y1); 
        }
    }
    int main(){       
        scanf("%d%d",&n,&m); 
        init(); 
        for(int i = 1;i <= n; ++i) scanf("%d%d",&node[i].p[0],&node[i].p[1]); 
        int root = build(1,n,0); 
        for(int i = 1;i <= m; ++i) {
            int opt,a,b; 
            scanf("%d%d%d",&opt,&a,&b);       
            if(opt == 1) {
                Data k; 
                k.p[0] = a,k.p[1] = b;        
                update(root,k,0);   
                if(i % 300000 == 0) root = build(1,tot,0);   
            }
            if(opt == 2) {
                ans = inf; 
                query(root,a,b); 
                printf("%d\n",ans); 
            }
        }
        return 0; 
    }     
}; 

  

15.分块

namespace Block{
    #define maxn 1000000  
    #define inf 100000000 
    int n,m;
    int arr[maxn],minv[maxn],belong[maxn];
    int block;
    void build(){
        memset(minv,127,sizeof(minv)); 
        scanf("%d",&m);
        block = sqrt(n); 
        for(int i = 1;i <= n; ++i) {
            scanf("%d",&arr[i]); 
            belong[i] = (i - 1) / block + 1; 
            minv[belong[i]] = min(minv[belong[i]],arr[i]); 
        }
        int query(int l,int r){
            int minn = inf; 
            for(int i = l;i <= min(belong[l] * block); ++i) minn=min(minn,arr[i]); 
            if(belong[l] != belong[r]) {
                for(int i = (belong[r] - 1) * block + 1;i <= r; ++i) 
                    minn = min(minn,arr[i]); 
            }
            for(int i = belong[l] + 1;i < belong[r]; ++i) minn=min(minn,minv[i]); 
            return minn; 
        }
    }T; 
    int main(){
        T.build();
        while(m--){
            int a,b; 
            scanf("%d%d",&a,&b); 
            printf("%d\n",T.query(a,b)); 
        }
        return 0; 
    }
}; 

  

 16.非旋转treap

namespace fhqtreap{
    #define maxn 1000000  
    typedef pair<int,int>par;
    #define mk make_pair
    int n,m,rt,tot; 
    int lz[maxn],val[maxn],key[maxn],rs[maxn],ls[maxn],sz[maxn]; 
    void up(int x){ sz[x]=sz[ls[x]]+sz[rs[x]]+1; }
    void pd(int x){
        if(!x||!lz[x]) return; 
        swap(ls[x],rs[x]),lz[x]^=1;
        if(ls[x]) lz[ls[x]]^=1;
        if(rs[x]) lz[rs[x]]^=1; 
    }
    par split(int x,int k){
        pd(x); 
        if(!k) return mk(0,x); 
        par t1,t2;
        int lson=ls[x],rson=rs[x];
        if(k==sz[ls[x]]) { ls[x]=0,up(x); return mk(lson,x);    }
        else if(k==sz[ls[x]]+1) { rs[x]=0,up(x); return mk(x,rson); }
        else if(k < sz[ls[x]]) {
            t1=split(ls[x],k); 
            ls[x]=t1.second,up(x); 
            return mk(t1.first,x); 
        }
        else {
            t1=split(rs[x],k-sz[ls[x]]-1); 
            rs[x]=t1.first,up(x); 
            return mk(x,t1.second); 
        }
    }
    int merge(int a,int b){
        if(!a||!b) return a+b; 
        pd(a),pd(b); 
        if(key[a]<key[b]){
            ls[b]=merge(a,ls[b]),up(b);
            return b;  
        }
        else{
            rs[a]=merge(rs[a],b),up(a); 
            return a; 
        }
    }
    void print(int x){
        if(!x) return;
        pd(x); 
        print(ls[x]),printf("%d ",val[x]),print(rs[x]); 
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) {
            key[++tot]=rand(),val[tot]=i,sz[tot]=1; 
            rt=merge(rt,tot); 
        }
        for(int x,y,i=1;i<=m;++i) {
            scanf("%d%d",&x,&y); 
            par t1=split(rt,y);     
            par t2=split(t1.first,x-1); 
            lz[t2.second]^=1; 
            merge(merge(t2.first,t2.second),t1.second); 
        }    
        print(rt); 
        return 0; 
    }
}; 

  

17.可持久treap

namespace fhqtreap{
    #define maxn 20000000   
    #define ll long long 
    int tot,m,tr;
    int trash[maxn]; 
    int ls[maxn],rs[maxn],rev[maxn],val[maxn],sz[maxn],key[maxn];  
    int root[maxn]; 
    ll sumv[maxn];
    ll lastans;   
    void ini(){
        tr=0; 
        for(int i=1;i<1000000;++i) trash[++tr]=i; 
        tot=1000001; 
    }
    int newnode(){ 
        return tr?trash[tr--]:++tot; 
    }
    int cpy(int p){   
        int x=newnode();     
        sz[x]=sz[p],ls[x]=ls[p],rs[x]=rs[p]; 
        rev[x]=rev[p],val[x]=val[p],key[x]=key[p],sumv[x]=sumv[p]; 
        return x; 
    }
    void up(int x){
        sz[x]=sz[ls[x]]+sz[rs[x]]+1;
        sumv[x]=sumv[ls[x]]+sumv[rs[x]]+(long long)val[x]; 
    }
    int New(int v){
        int p=newnode(); 
        sz[p]=1,ls[p]=rs[p]=0,sumv[p]=val[p]=v,key[p]=rand(),rev[p]=0; 
        return p; 
    }
    void era(int x){
        sz[x]=ls[x]=rs[x]=rev[x]=val[x]=sumv[x]=key[x]=0; 
        trash[++tr]=x; 
    }
    void pd(int x){
        if(!x||!rev[x]) return;     
        if(rev[x]){
            swap(ls[x],rs[x]);
            if(ls[x]) ls[x]=cpy(ls[x]),rev[ls[x]]^=1;
            if(rs[x]) rs[x]=cpy(rs[x]),rev[rs[x]]^=1; 
            rev[x]=0; 
        }
    }
    void split(int x,int k,int &l,int &r){
        if(x){
            pd(x); 
            if(k<=sz[ls[x]]) {
                r=cpy(x);     
                split(ls[r],k,l,ls[r]);  
                up(r); 
            }
            else {
                l=cpy(x); 
                split(rs[l],k-sz[ls[l]]-1,rs[l],r);   
                up(l);  
            }
        }else l=r=0; 
    }
    int mg(int l,int r){
        if(l&&r){
            if(key[l]<key[r]) {
                pd(r),ls[r]=mg(l,ls[r]),up(r); 
                return r; 
            }else {
                pd(l),rs[l]=mg(rs[l],r),up(l); 
                return l; 
            }
        }else return l+r;     
    }         
    void ins(int &rt,int p,int v){
        int x,y; 
        split(rt,p,x,y);         
        rt=mg(mg(x,New(v)),y);  
    }
    void Del(int &rt,int p){      
        int x,y,z; 
        split(rt,p,x,y),split(x,p-1,x,z),era(z); 
        rt=mg(x,y); 
    }
    void Rev(int &rt,int L,int R){
        int x,y,z; 
        split(rt,R,x,y),split(x,L-1,x,z),rev[z]^=1; 
        rt=mg(mg(x,z),y); 
    }
    void Q(int &rt,int L,int R){
        int x,y,z; 
        split(rt,R,x,y),split(x,L-1,x,z), printf("%lld\n",(lastans=sumv[z])); 
        rt=mg(mg(x,z),y); 
    }
    int main(){
        ini();
        int n,a=0,b=0; 
        scanf("%d",&n); 
        for(int opt,v,i=1;i<=n;++i){
            scanf("%d%d",&v,&opt); 
            root[i]=root[v]; 
            scanf("%d",&a),a^=lastans; 
            if(opt!=2) scanf("%d",&b),b^=lastans; 
            if(opt==1) ins(root[i],a,b); 
            if(opt==2) Del(root[i],a); 
            if(opt==3) Rev(root[i],a,b); 
            if(opt==4) Q(root[i],a,b); 
        }
        return 0; 
    }
}; 

 

18.点分治

void add(int u,int v,int c){ nex[++cnt]=head[u],head[u]=cnt,to[cnt]=v,val[cnt]=c;  }
//求重心
void get(int x,int fa){
    f[x]=0,siz[x]=1;
    for(int v=head[x];v;v=nex[v]){
        if(to[v]==fa||vis[to[v]]) continue;
        get(to[v],x);
        siz[x]+=siz[to[v]];
        f[x]=max(f[x],siz[to[v]]);
    }     
    f[x]=max(f[x],sn-siz[x]);
    if(f[x]<f[root]) root=x;
}
void getdis(int x,int fa){
    d[++tot]=dep[x];
    for(int v=head[x];v;v=nex[v]){
        if(to[v]==fa||vis[to[v]]) continue;
        dep[to[v]]=dep[x]+val[v],getdis(to[v],x);
    }
}
int calc(int x){    
    tot=0;
    getdis(x,0);
    sort(d+1,d+tot+1); 
    int i=1,j=tot,sum=0;
    while(i<j) {
        if(d[i]+d[j]<=m) {
            sum+=j-i,i++; 
        }
        else j--;             
    }
    return sum;
}
void dfs(int x){
    dep[x]=0;
    vis[x]=1;
    ans+=calc(x);
    for(int v=head[x];v;v=nex[v]){
        if(!vis[to[v]]) {
            dep[to[v]]=val[v];
            ans-=calc(to[v]);         
            sn=siz[to[v]];
            root=0;
            get(to[v],0);
            dfs(root);
        }
    }
}

  

19.动态点分治

#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 6011111
#define N 500010 
#define inf 0x7f7f7f
using namespace std;
int hd[N],nx[N],to[N],cnt;
int n,m,val[N],vis[N];
void add(int u,int v)
{
    nx[++cnt]=hd[u],hd[u]=cnt,to[cnt]=v;
}
namespace heavyedge{
    int dep[N],hson[N],fa[N],siz[N],top[N];
    void dfs1(int u,int ff)
    {
        dep[u]=dep[ff]+1,fa[u]=ff,siz[u]=1;          
        for(int i=hd[u];i;i=nx[i])
            if(to[i]!=ff)
            {
                dfs1(to[i],u),siz[u]+=siz[to[i]];
                if(siz[to[i]]>siz[hson[u]]) hson[u]=to[i];
            }
    }
    void dfs2(int u,int tp)   
    {  
        top[u]=tp;
        if(hson[u]) dfs2(hson[u],tp);
        for(int i=hd[u];i;i=nx[i])
        {
            if(to[i]==fa[u]||to[i]==hson[u]) continue;
            dfs2(to[i],to[i]);
        }
    }
    int LCA(int u,int v)
    {
        while(top[u]!=top[v]) dep[top[u]] < dep[top[v]] ? v = fa[top[v]] : u = fa[top[u]]; 
        return dep[u] < dep[v] ? u : v;
    }
    int main()
    {
        dfs1(1,0), dfs2(1,1);
        return 0;
    }
};  
int Dis(int u,int v)
{ 
    return heavyedge::dep[u] + heavyedge::dep[v] - (heavyedge::dep[heavyedge::LCA(u,v)] << 1);
}  
int siz[N],f[N],root,sn,Fa[N];
int GetRoot(int u,int ff)
{
    siz[u] = 1,f[u] = 0;
    for(int i = hd[u]; i ; i = nx[i])
    {
        if(to[i] == ff || vis[to[i]]) continue;
        GetRoot(to[i],u);    
        siz[u] += siz[to[i]];
        f[u] = max(f[u],siz[to[i]]);
    }
     
    f[u] = max(f[u],sn - siz[u]);
    if(f[u] < f[root]) root = u;
}
void dfs(int u)
{
    vis[u] = 1;
    for(int i = hd[u]; i ; i = nx[i])
    {
        if(vis[to[i]]) continue;
        root = 0, sn = siz[to[i]], GetRoot(to[i],u); 
        Fa[root] = u, dfs(root);
    }
}
struct Segment_Tree{
    #define ls (t[o].l)
    #define rs (t[o].r)
    int tot;
    struct Node
    {
        int l,r,v;
    }t[maxn<<1];
    void update(int &o,int l,int r,int p,int w)
    {
        if(!o) o = ++cnt;
        t[o].v += w;
        if(l == r) return;
        int mid = (l + r) >> 1;
        if(p <= mid) update(t[o].l,l,mid,p,w);
        else update(t[o].r,mid + 1,r,p,w);
    }
     
    int query(int o,int l,int r,int L,int R)
    {
        if(!o || l > r) return 0;
        if(l >= L && r <= R) return t[o].v;
        int mid = (l + r) >> 1,res = 0;  
        if(L <= mid) res += query(t[o].l,l,mid,L,R);
        if(R >= mid + 1) res += query(t[o].r,mid + 1,r, L,R);
        return res;
    }
}T;
int ans = 0,rt[N];
#define fax(x) (x + n)         
void Update(int x,int k,int w)
{
    T.update(rt[x],0,n,0,w),T.update(rt[x],0,n,k + 1,-w);        
    for(int i = x; Fa[i]; i = Fa[i])        
    {
        int dis = Dis(x, Fa[i]);  
        if(k - dis < 0) continue;
        T.update(rt[Fa[i]],0,n,0,w),T.update(rt[Fa[i]],0,n,k - dis + 1,-w);
        T.update(rt[fax(i)],0,n,0,w),T.update(rt[fax(i)],0,n,k - dis + 1,-w);
    }
}
int Query(int x)
{
    int res = T.query(rt[x],0,n,0,0);
    for(int i = x; Fa[i] ; i = Fa[i])
    {
        int dis = Dis(x, Fa[i]);
        res += T.query(rt[Fa[i]],0,n,0,dis);
        res -= T.query(rt[fax(i)],0,n,0,dis);
    }     
    return res;
}
char str[20];      
int main()
{       
    // setIO("input");
    scanf("%d%d",&n,&m);
    for(int i = 1,u,v;i < n; ++i)  scanf("%d%d",&u,&v), add(u,v),add(v,u);
    heavyedge :: main();      
    f[0] = inf, sn = n,root = 0,GetRoot(1,0), dfs(root);      
    while(m--)
    {
        int x,y,z;
        scanf("%s",str);      
        if(str[0] == 'M') scanf("%d%d%d",&x,&y,&z),Update(x,y,z);   
        if(str[0] == 'Q') scanf("%d",&x), printf("%d\n",Query(x));
    }     
    return 0;
} 

  

posted @ 2019-04-04 16:14  EM-LGH  阅读(280)  评论(0编辑  收藏  举报