• [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
    ", 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:
    ",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
    ",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
    ",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

  • 相关阅读:
    当前毫秒时间戳
    生成随机指定长度的字符串
    symfony框架学习
    Git 学习一
    jmeter逻辑控制器
    jmeter执行顺序及作用域规则
    jmeter常用测试元件
    windows环境下jmeter生成测试报告
    jmeter参数化
    对网页进行截图(selenium)
  • 原文地址:https://www.cnblogs.com/SinGuLaRiTy2001/p/7674819.html
Copyright © 2020-2023  润新知