[SinGuLaRiTy] 复习模板-数据结构

Posted SinGuLaRiTy2001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SinGuLaRiTy] 复习模板-数据结构相关的知识,希望对你有一定的参考价值。

【SinGuLaRiTy-1040】 Copyright (c) SinGuLaRiTy 2017. All Rights Reserved.

二维线段树 2D_Segment_Tree

//示例:单点修改,区间求和。
//注意内存限制
#include<cstdio> 
#include<iostream>
#include<cstring>
const int MAXN = 1025;
#define L(x) ((x)<<1)
#define R(x) ((x)<<1|1)
#define M(x,y) (((x)+(y))>>1)
using namespace std;
int N, ans;
struct Node {
    short l, r;
    int sum;
} a[MAXN*4][MAXN*4];
int refer[MAXN];
void build_y(int &xid, int i, short l, short r)
{
    a[xid][i].l = l;
    a[xid][i].r = r;
    if (l == r) return;
    build_y(xid, L(i), l, M(l,r));
    build_y(xid, R(i), M(l,r)+1, r);
}
void build_x(int i, short l, short r)
{
    a[0][i].l = l;
    a[0][i].r = r;
    build_y(i, 1, 0, N);
    if (l==r) { refer[l]=i; return; }
    build_x(L(i), l, M(l,r));
    build_x(R(i), M(l,r)+1, r);
}

void update(int x, int y, int &dt)
{
    int i = refer[x], j;
    while (i>0) {
        j = refer[y];
        while (j>0)
            a[i][j].sum += dt, j >>= 1;
        i >>= 1;
    }
}
void sum_y(int& xid, int i, int& y1, int& y2)
{
    if (a[xid][i].l > y2 || a[xid][i].r < y1)
        return;
    if (a[xid][i].l >= y1 && a[xid][i].r <= y2)
    {
        ans += a[xid][i].sum;
        return;
    }
    sum_y(xid, L(i), y1, y2);
    sum_y(xid, R(i), y1, y2);
}
void sum_x(int i, int& x1, int& y1, int& x2, int& y2)
{
    if (a[0][i].l > x2 || a[0][i].r < x1)
        return;
    if (a[0][i].l >= x1 && a[0][i].r <= x2)
    {
        sum_y(i, 1, y1, y2);
        return;
    }
    sum_x(L(i), x1, y1, x2, y2);
    sum_x(R(i), x1, y1, x2, y2);
}

int main()
{
    int op, x1, y1, x2, y2, t;
    scanf("%d%d", &N, &N);
    build_x(1, 0, N);
    while (scanf("%d", &op) && op!=3)
    {
        if (op == 1)
        {
            scanf("%d%d%d", &x1, &y1, &t);
            update(x1, y1, t);
        }
        else
        {
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            ans = 0;
            sum_x(1, x1, y1, x2, y2);
            printf("%d\n", ans);
        }
    } 
    return 0;
}

双向队列 deque

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 100010;

struct Deque
{
    int nxt[MAXN], prv[MAXN], stk[MAXN], tp;
    int val[MAXN];
    int f, b, size, t;
    void clear() {
        f=b=size=0; tp=MAXN-2;
        for (int i=1; i<MAXN; ++i)
            nxt[i] = prv[i] = 0, stk[i] = i;
    }
    Deque() { clear(); }
    void push(bool d, int v)
    {
        if (!size) { f = b = stk[tp--]; val[f] = v; prv[f]=nxt[f]=0; }
        else {
            t = stk[tp--];
            if (d) { nxt[b] = t; prv[t] = b; nxt[t] = 0; val[t] = v; b = t;}
            else { nxt[t] = f; prv[f] = t; prv[t] = 0; val[t] = v; f = t; }
        }
        ++size;
    }
    void pop(bool d)
    {
        --size;
        if (d) stk[++tp] = b, b = prv[b];
        else stk[++tp] = f, f = nxt[f];
    }
    int front() { return val[f]; }
    int back() { return val[b]; }
} q;

int main()
{
    
    return 0;
}

Splay平衡树 Splay_Tree

#include<iostream>
#include<cstdio>
#include<cstring>
#define Max(a,b) ((a)>(b)?(a):(b))
#define L(x) x->ch[0]
#define R(x) x->ch[1]
using namespace std;
const int MAXN = 100010;

struct Node {
    int sz;
    Node *fa, *ch[2];
    Node () { sz=0; }
}nil, *NIL=&nil;

struct SeqSplay //用来维护区间操作的splay
{
    Node a[MAXN], *root;
    void init() { root=NIL; }
    inline void pushup(Node *x) {
        x->sz = L(x)->sz + R(x)->sz + 1;//size域一定要维护
        
    }
    inline void pushdown(Node *x) {
        //标记下放或者左右交换
        
    }
    void rotate(Node *x, int d) // 0左1右
    {
        Node *y = x->fa;
        if (y==root) root = x;
        pushdown(y); pushdown(x);
        y->ch[!d] = x->ch[d];
        if (x->ch[d] != NIL)
            x->ch[d]->fa = y;
        x->fa = y->fa;
        if (y->fa != NIL)
            y->fa->ch[ y->fa->ch[1]==y ] = x;
        x->ch[d] = y;
        y->fa = x;
        pushup(y); pushup(x);
    }
    void splay(Node*x, Node*target)//双旋至target以下
    {
        Node *y, *z;
        while (x->fa != target) {
            y = x->fa; z = y->fa;
            pushdown(x);
            if (z == target) {
                rotate(x, x==y->ch[0]);
                return;
            }
            if (y == L(z))
                if (x == L(y)) rotate(y, 1), rotate(x, 1);
                else rotate(x, 0), rotate(x, 1);
            else
                if (x == R(y)) rotate(y, 0), rotate(x, 0);
                else rotate(x, 1), rotate(x, 0);
            pushup(x);
        }
    }
    Node* build(int l, int r, Node* fa)
    {
        if (l>r) return NIL;
        int mid = (l+r)>>1;
        a[mid].ch[0] = build(l, mid-1, &a[mid]);
        a[mid].ch[1] = build(mid+1, r, &a[mid]);
        
        //此处根据题意具体录入节点内容
        pushup(&a[mid]);
        return &a[mid];
    }
    void init(int l, int r) { //伸展树的初始化,外部调用时一定要空置左右端点
        root = build(l, r, NIL);
    }
    void getkth(int k, Node *&target)//将第k个元素旋转至target下面
    {
        Node *t = root;
        while (1) {
            pushdown(t);
            if (k == (t->ch[0]->sz)+1) {
                splay(t, target);
                return;
            }
            if (k <= L(t)->sz) t = L(t);
            else k-=L(t)->sz+1, t = R(t);
        }
    }
    void form(int l, int r) //将区间[l,r]旋转至操作区域
    {
        getkth(l, root);
        getkth(r+2, R(root));
    }
    
} tree;

int main()
{
    
    return 0;
}

线段树

struct node
{
    int l ,r ,sum ;
}tre[MAXN<<2] ;

void build(int code,int l,int r)
{
    tre[code].l=l ,tre[code].r=r ;
    if(l==r)return;
    build(code*2,l,(l+r)/2);
    build(code*2+1,(l+r)/2+1,r);
}

void update(int code,int l,int r)
{
    if(l<=tre[code].l&&tre[code].r<=r)
    {
        //修改
        return;
    }
    //若有懒标记 pushdown();
    int mid=(tre[code].l+tre[code].r)/2;
    if(l<=mid)update(code*2,l,r);
    if(mid<r)update(code*2+1,l,r);
    //更新 pushup();
    tre[code].sum=tre[code*2].sum+tre[code*2+1].sum;
}

int query(int code,int l,int r)
{
    if(l<=tre[code].l&&tre[code].r<=r)
        return tre[code].sum;
    int mid=(tre[code].l+tre[code].r)/2 ,ans=0 ;
    //pushdown();
    if(l<=mid)ans+=query(code*2,l,r);
    if(mid<r)ans+=query(code*2+1,l,r);
    return ans;
}

二维树状数组

#define LL long long int
#define lowbit(a) ((a)&(-(a)))
LL tre[MAXN+5][MAXN+5] ;
void update(int a,int b,LL val)
{
    val%=mod;
    for(;a<=n;a+=lowbit(a))
        for(int j=y;j<=m;j+=lowbit(j))
        {
            tre[i][j]+=val;
            if(tre[a][j]>=mod)tre[a][j]-=mod;
        }
}

LL getsum(int x,int y)
{
    LL ans=0;
    for(;x>0;x-=lowbit(x))
        for(int j=y;j>0;j-=lowbit(j))
        {
            ans+=tre[x][j];
            if(ans>=mod)ans-=mod;
        }
    return ans;
}

树状数组

#define lowbit(a) ((a)&(-(a)))
#define LL long long int
LL tre[MAXN+5] ;
void update(LL a,int pos)
{
    a%=mod;
    while(pos<=n)
    {
        tre[pos]+=a;
        if(tre[pos]>=mod)tre[pos]-=mod;
        pos+=lowbit(pos);
    }
}

LL getsum(int pos)
{
    LL ans=0 ;
    while(pos>0)
    {
        ans+=tre[pos];
        if(ans>=mod)ans-=mod;
        pos-=lowbit(pos);
    }
    return ans;
}

并查集

int getroot(int a)
{
    if(fa[a]==a)return a;
    return fa[a]=getroot(fa[a]);
}

void Union(int a,int b)
{
    fa[getroot(a)]=getroot(b);
}

 

以上是关于[SinGuLaRiTy] 复习模板-数据结构的主要内容,如果未能解决你的问题,请参考以下文章

[SinGuLaRiTy] 复习模板-数学

[SinGuLaRiTy] 复习模板-树

[SinGuLaRiTy] 图论题目复习

[SinGuLaRiTy] 数论题目复习

[SinGuLaRiTy] 贪心题目复习

[SinGuLaRiTy] 分治题目复习