[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);
}

归并排序

///归并排序模板。记得和快排一块对着看。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define LL long long
#define inf 0x3f3f3f3f
#define mod 1e9+7
const int maxn=1e5+5;
using namespace std;
int temp[maxn];
int num=0;///统计逆序对数的。
void Merge(int a[],int left ,int mid,int right)
{
    int i=left,j=mid+1,n=0,length=right-left;///i开始为左半部分最左边,j为右半部分最左边。temp数组是从下标0开始存数。
    while(i<=mid&&j<=right){
        if(a[i]>a[j]){///左边比右边大。
            temp[n++]=a[j++];
            num+=mid-i+1;///从i到mid都是比a[j]大。
        }
        else{
            temp[n++]=a[i++];
        }
    }
    if(i>mid){///这里说明的是左边全部填满了(因为前面的判断条件是i<=mid,那就是天右边了。
        while(j<=right){
            temp[n++]=a[j++];
        }
    }
    else{
        while(i<=mid){
            temp[n++]=a[i++];
        }
    }
    for(int k=0;k<=length;k++){///最后赋值到原数组必须要有的。
        a[left+k]=temp[k];
    }
}
void mergesort(int a[],int left,int right)
{
    if(left<right){
        int mid=(left+right)/2;
        mergesort(a,left,mid);
        mergesort(a,mid+1,right);
        Merge(a,left,mid,right);
    }
}
int main()
{
    int number[30] = {};
    mergesort(number,0,30-1);///初始化调用也要注意额。

    for(int i=0;i<30;i++){
        printf("%d ",number[i]);
    }
}

堆排序

int adjust_heap(vector<int> &v, int length, int i){
        int left = 2 * i;
        int right = 2 * i + 1;
        int largest = i;
        int temp;

        while(left < length || right < length){
                if (left < length && v[largest] < v[left]){
                        largest = left;
                }
                if (right < length && v[largest] < v[right]){
                        largest = right;
                }

                if (i != largest){
                        temp = v[largest];
                        v[largest] = v[i];
                        v[i] = temp;
                        i = largest;
                        left = 2 * i;
                        right = 2 * i + 1;
                }
                else{
                        break;
                }
        }
}

int build_heap(vector<int> &v, int length){
        int i;
        int begin = length/2 - 1; //get the last parent node
        for (i = begin; i>=0; i--){
                adjust_heap(v,length,i);
        }
}

int heap_sort(vector<int> &v){
        int length = v.size();
        int temp;
        printline("before sort:",v);
        build_heap(v,length);
        while(length > 1){
                temp = v[length-1];
                v[length-1] = v[0];
                v[0] = temp;
                length--;
                adjust_heap(v,length,0);
        }
        printline("after sort:",v);
}

线段树(update:单点增减; query:区间求和) - HDU1166 敌兵布阵

#include <cstdio>
 
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 55555;
int sum[maxn<<2];
void PushUP(int rt) {
       sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void build(int l,int r,int rt) {
       if (l == r) {
              scanf("%d",&sum[rt]);
              return ;
       }
       int m = (l + r) >> 1;
       build(lson);
       build(rson);
       PushUP(rt);
}
void update(int p,int add,int l,int r,int rt) {
       if (l == r) {
              sum[rt] += add;
              return ;
       }
       int m = (l + r) >> 1;
       if (p <= m) update(p , add , lson);
       else update(p , add , rson);
       PushUP(rt);
}
int query(int L,int R,int l,int r,int rt) {
       if (L <= l && r <= R) {
              return sum[rt];
       }
       int m = (l + r) >> 1;
       int ret = 0;
       if (L <= m) ret += query(L , R , lson);
       if (R > m) ret += query(L , R , rson);
       return ret;
}
int main() {
       int T , n;
       scanf("%d",&T);
       for (int cas = 1 ; cas <= T ; cas ++) {
              printf("Case %d:\n",cas);
              scanf("%d",&n);
              build(1 , n , 1);
              char op[10];
              while (scanf("%s",op)) {
                     if (op[0] == 'E') break;
                     int a , b;
                     scanf("%d%d",&a,&b);
                     if (op[0] == 'Q') printf("%d\n",query(a , b , 1 , n , 1));
                     else if (op[0] == 'S') update(a , -b , 1 , n , 1);
                     else update(a , b , 1 , n , 1);
              }
       }
       return 0;
}

树的点分治-找出树中有多少点对,满足dis(u,k)<K

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=10010;
int N,K;
int ans,root,Max;
struct node
{
    int v,next,w;
}edge[maxn*2];
int head[maxn],tot;
int size[maxn];//树的大小
int maxv[maxn];//最大孩子节点的size
int vis[maxn];
int dis[maxn];
int num;
void init()
{
    tot=0;
    ans=0;
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
}
void add_edge(int u,int v,int w)
{
    edge[tot].v=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}
//处理子树的大小
void dfssize(int u,int f)
{
    size[u]=1;
    maxv[u]=0;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==f||vis[v])continue;
        dfssize(v,u);
        size[u]+=size[v];
        if(size[v]>maxv[u])maxv[u]=size[v];
    }
}
//找重心
void dfsroot(int r,int u,int f)
{
    if(size[r]-size[u]>maxv[u])//size[r]-size[u]是u上面部分的树的尺寸,跟u的最大孩子比,找到最大孩子的最小差值节点
        maxv[u]=size[r]-size[u];
    if(maxv[u]<Max)Max=maxv[u],root=u;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==f||vis[v])continue;
        dfsroot(r,v,u);
    }
}
//求每个点离重心的距离
void dfsdis(int u,int d,int f)
{
    dis[num++]=d;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v!=f&&!vis[v])
            dfsdis(v,d+edge[i].w,u);
    }
}
//计算以u为根的子树中有多少点对的距离小于等于K
int calc(int u,int d)
{
    int ret=0;
    num=0;
    dfsdis(u,d,0);
    sort(dis,dis+num);
    int i=0,j=num-1;
    while(i<j)
    {
        while(dis[i]+dis[j]>K&&i<j)j--;
        ret+=j-i;
        i++;
    }
    return ret;
}
void dfs(int u)
{
    Max=N;
    dfssize(u,0);
    dfsroot(u,u,0);
    ans+=calc(root,0);
    vis[root]=1;
    for(int i=head[root];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(!vis[v])
        {
            ans-=calc(v,edge[i].w);
            dfs(v);
        }
    }
}
int main()
{
    while(scanf("%d%d",&N,&K)!=EOF)
    {
        if(!N&&!K)break;
        int u,v,w;
        init();
        for(int i=1;i<N;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add_edge(u,v,w);
            add_edge(v,u,w);
        }

        dfs(1);
        printf("%d\n",ans);
    }
    return 0;
}

Lower_bound & Upper_bound

ForwardIterator my_lower_bound(ForwardIterator beg, ForwardIterator end, T target)
{
    ForwardIterator mid;
    typename iterator_traits<ForwardIterator>::difference_type count, step;

    count = distance(beg, end);
    while(count > 0)
    {
        mid = beg;
        step = count/2;
        advance(mid, step);
        if(*mid < target) //mid < target
        {
            beg = ++mid;
            count -= (step+1); //count表示当前数组中还有的元素个数
        }
        else
        {
            count = step;
        }
    }
    return beg;
}
template<class ForwardIterator, class T>
ForwardIterator my_upper_bound(ForwardIterator beg, ForwardIterator end, T target)
{
    ForwardIterator mid;
    typename iterator_traits<ForwardIterator>::difference_type count, step;

    count = distance(beg, end);
    while(count > 0)
    {
        mid = beg;
        step = count/2;
        advance(mid, step);
        if(target < *mid) //mid < target
        {
            count = step;
        }
        else
        {
            beg = ++mid;
            count -= (step+1);
        }
    }
    return beg;
}

二分查找

//递归版本
int  binarySearchRecusion(int* array,int len,int value){
    if(len==0)
        return -1;

    int mid=(len-1)/2;
    if(array[mid]==value)
        return mid;
    if(array[mid]>value)                        //在右半区
        binarySearchRecusion(array+mid+1,len-mid-1,value);
    else
        binarySearchRecusion(array,mid,value);  //在左半区
}
//非递归版本
//有序数组递减排列
int  binarySearch(int* array,int len,int value){
    int mid=0;
    int low=0;
    int high=len-1;
    while(low<=high){
        mid=(low+high)/2;
        if(array[mid]>value){       //在右半区
            low=mid+1;
            continue;
        }
        else if(array[mid]<value){  //在左半区
            high=mid-1;
            continue;
        }else
            return mid;             //找到
    }
    return -1;   //查找失败
}

三分查找

double solve(double MIN,double MAX)
{
    double Left, Right;
    double mid, midmid;
    double mid_value, midmid_value;
    Left = MIN;
    Right = MAX;
    while (Left +eps < Right)
    {
        mid = (Left + Right) / 2;
        midmid = (mid + Right) / 2;
        mid_value = Calc(mid); //Cal()为题意规定的计算内容
        midmid_value = Calc(midmid);
        ///求最大值改成>= 最小值改成<=
        if (mid_value >= midmid_value) Right = midmid;
        else Left = mid;
    }
    return Left;
}

 

Time: 2017-10-17

posted @ 2017-10-17 23:25  SinGuLaRiTy2001  阅读(230)  评论(0编辑  收藏  举报