程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 3468 A Simple Problem with Integers (伸展樹區間更新求和操作 , 模板)

POJ 3468 A Simple Problem with Integers (伸展樹區間更新求和操作 , 模板)

編輯:C++入門知識

 這是樣例中的數據輸入後建成的樹,其中的1,2是加入的邊界頂點,數字代表節點編號,我們如果要對一段區間[l, r]進行操作,只需要把第l-1位的數旋轉到0節點下面,把r+1位的數旋轉到當前的root下面,就如上圖所示,那麼橢圓裡表示的就是區間[l, r]。

附上注釋代碼。指針版本的比靜態數組的快1s多。。

/* **********************************************
Author      : JayYe
Created Time: 2013-8-16 11:14:36
File Name   : zzz.cpp
*********************************************** */

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

#define LL __int64
#define keytree (ch[ ch[root][1] ][0])
#define lson ch[x][0]
#define rson ch[x][1]

const int maxn = 111111;

struct Splaytree {

    int pre[maxn], ch[maxn][2], sz[maxn];
    int root, top;
    // 旋轉操作, c = 0代表左旋, c = 1代表右旋
    void Rotate(int x, int c) {
        int y = pre[x];
        push_down(y), push_down(x);
        ch[y][!c] = ch[x][c];
        pre[ch[x][c]] = y;
        if(pre[y])  ch[pre[y]][ ch[pre[y]][1] == y ] = x;
        pre[x] = pre[y];
        ch[x][c] = y;
        pre[y] = x;
        push_up(y);
    }
    // Splay 操作, 把 x 節點轉到go的下面
    void Splay(int x, int go) {
        while(pre[x] != go) {
            if(pre[pre[x]] == go) {
                Rotate(x, ch[pre[x]][0] == x);
            }
            else {
                int y = pre[x] , z = pre[y];
                int f = (ch[z][1] == y);
                if(ch[y][f] == x)  
                    Rotate(y, !f), Rotate(x, !f); // 一字型旋轉
                else
                    Rotate(x, f), Rotate(x, !f); // 之字型旋轉
            }
        }
        push_up(x);
        if(go == 0) root = x;
    }
    // 將第k位的數旋轉到go的下面
    void RotateTo(int k, int go) {
        int x = root;
        push_down(root);
        while(sz[lson] != k) {
            if(k < sz[lson]) {
                x = lson;
            }
            else {
                k -= sz[lson] + 1;
                x = rson;
            }
            push_down(x);
        }
        Splay(x, go);
    }

    void debug() {printf("%d\n",root);Treaval(root);}
	void Treaval(int x) {
		if(x) {
			Treaval(ch[x][0]);
			printf("結點%2d:左兒子 %2d 右兒子 %2d 父結點 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
			Treaval(ch[x][1]);
		}
	}
    

    int val[maxn], add[maxn], a[maxn];
    LL sum[maxn];
    // 把兒子節點的信息更新上來
    void push_up(int x) {
        sz[x] = sz[lson] + sz[rson] + 1;
        sum[x] = val[x] + add[x] + sum[lson] + sum[rson];
    }
    // 標記下傳
    void push_down(int x) {
        if(add[x]) {
            val[x] += add[x];
            add[lson] += add[x];
            add[rson] += add[x];
            sum[lson] += (LL)add[x]*sz[lson];
            sum[rson] += (LL)add[x]*sz[rson];
            add[x] = 0;
        }
    }
    
    void newnode(int &x, int c)  {
        x = ++top;
        lson = rson = 0;
        sz[x] = 1;
        val[x] = sum[x] = c;
        add[x] = 0;
    }

    void build(int &x, int l, int r, int f) {
        if(l > r)   return ;
        int mid = (l+r)/2;
        newnode(x, a[mid]);
        build(lson, l, mid-1, x);
        build(rson, mid+1, r, x);
        pre[x] = f;
        push_up(x);
    }

    void init(int n) {
        ch[0][0] = ch[0][1] = pre[0] = 0;
        top = root = 0;
        newnode(root, -1);
        newnode(ch[root][1], -1);
        // 為了方便處理邊界,加兩個邊界頂點
        pre[top] = root;
        sz[root] = 2;

        for(int i = 0;i < n; i++)   scanf("%d", &a[i]);
        build(keytree, 0, n-1, ch[root][1]);
        push_up(ch[root][1]);
        push_up(root);
    }

    void update(int l ,int r, int c) {
        RotateTo(l-1, 0);
        RotateTo(r+1, root);
        add[keytree] += c;
        sum[keytree] += (LL)c*sz[keytree];
    }

    LL query(int l, int r) {
        RotateTo(l-1, 0);
        RotateTo(r+1, root);
        return sum[keytree];
    }

}spt;

int main() {
    int n, m, l, r, c;
    char s[2];
    scanf("%d%d", &n, &m);
    spt.init(n);
    while(m--) {
        scanf("%s%d%d", s, &l, &r);
        if(s[0] == 'Q')
            printf("%I64d\n", spt.query(l, r));
        else {
            scanf("%d", &c);
            spt.update(l, r, c);
        }
    }
    return 0;
}
/* **********************************************
Author      : JayYe
Created Time: 2013-8-16 15:19:38
File Name   : zzz.cpp
*********************************************** */

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

#define LL __int64
#define keytree (root->ch[1]->ch[0])
#define lson x->ch[0]
#define rson x->ch[1]

const int maxn = 111111;

struct NODE {
    struct NODE *ch[2], *pre;
    int add, val, sz, id;
    LL sum;
    void push_down() {
        if(add) {
            val += add;
            if(ch[0]) {
                ch[0]->add += add;
                ch[0]->sum += (LL)add*ch[0]->sz;
            }
            if(ch[1]) {
                ch[1]->add += add;
                ch[1]->sum += (LL)add*ch[1]->sz;
            }
            add = 0;
        }
    }
    
    void push_up() {
        sz = ch[0]->sz + ch[1]->sz + 1;
        sum = val + add + ch[0]->sum + ch[1]->sum;
    }

}node[maxn], *null = &node[0], *root;

struct Splaytree {

    int top;
    // 旋轉操作, c = 0代表左旋, c = 1代表右旋  
    void Rotate(NODE *x, int c) {
        NODE *y = x->pre;
        y->push_down(), x->push_down();
        y->ch[!c] = x->ch[c];
        x->ch[c]->pre = y;
        x->pre = y->pre;
        if(y->pre != NULL)  y->pre->ch[ y->pre->ch[1] == y] = x;
        x->ch[c] = y;
        y->pre = x;
        y->push_up();
    }
    // Splay 操作, 把 x 節點轉到go的下面 
    void Splay(NODE *x, NODE *go) {
        while(x->pre != go) {
            if(x->pre->pre == go) {
                Rotate(x, x->pre->ch[0] == x);
            }
            else {
                NODE *y = x->pre, *z = y->pre;
                int f = (z->ch[1] == y);
                if(y->ch[f] == x)
                    Rotate(y, !f) , Rotate(x, !f); // 一字型旋轉 
                else
                    Rotate(x, f) , Rotate(x, !f); // 之字型旋轉 
            }
        }
        x->push_up();
        if(go == null)  root = x;
    }
    // 將第k位的數旋轉到go的下面  
    void RotateTo(int k, NODE *go) {
        NODE *x = root;
        x->push_down();
        while(lson->sz != k) {
            if(lson->sz > k) {
                x = lson;
            }
            else {
                k -= lson->sz + 1;
                x = rson;
            }
            x->push_down();
        }
        Splay(x, go);
    }

    void debug(NODE *x) {
        if(x != null) {
            printf("節點: %2d  左兒子: %2d 右兒子: %2d size = %2d val = %2d\n", 
                x->id, x->ch[0]->id, x->ch[1]->id, x->sz, x->val);
            debug(x->ch[0]);
            debug(x->ch[1]);
        }
    } 
    
    int a[maxn];

    NODE *newnode(NODE* f, int c) {
        NODE *x = &node[++top];
        x->id = top;
        x->val = x->sum = c;
        x->ch[0] = x->ch[1] = null;
        x->sz = 1;
        x->add = 0;
        x->pre = f;
        return x;
    }

    void build(NODE* &x, int l, int r, NODE *f) {
        if(l > r)   return ;
        int mid = (l+r)/2;
        x = newnode(f, a[mid]);
        build(lson, l, mid-1, x);
        build(rson, mid+1, r, x);
        x->push_up();
    }

    void init(int n) {
        null->id = 0;
        null->ch[0] = null->ch[1] = NULL;
        null->sz = null->add = null->sum = null->val = 0;
//      null->pre = NULL;
        top = 0;
        root = newnode(null, -1);
        root->ch[1] = newnode(root, -1);

        for(int i = 0;i < n; i++)   scanf("%d", &a[i]); 
        build(keytree, 0, n-1, root->ch[1]);
        root->ch[1]->push_up();  root->push_up();
    }

    void update() {
        int l, r, c;
        scanf("%d%d%d", &l, &r, &c);
        RotateTo(l-1, null);
        RotateTo(r+1, root);
        keytree->add += c;
        keytree->sum += (LL)c*keytree->sz;
    }

    void query() {
        int l, r;
        scanf("%d%d", &l, &r);
        RotateTo(l-1, null);
        RotateTo(r+1, root);
        printf("%I64d\n", keytree->sum);
    }
}spt;

int main() {
    int n, m;
    char s[2];
    scanf("%d%d", &n, &m);
    spt.init(n);   
    while(m--) {
        scanf("%s", s);
        if(s[0] == 'Q')
            spt.query();
        else
            spt.update();
    }
    return 0;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved