POJ3468 A Simple Problem with Integers 线段树模板

9 篇文章 0 订阅
4 篇文章 0 订阅

http://poj.org/problem?id=3468

线段树模板题, 不多说…
板子贴上

ac代码

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;

const unsigned int MAX = 1e5+10;
unsigned int n, q, ITOR, sl, sr;
long long sn;
char c;
struct RMQ{
    unsigned int l, r;
    unsigned int nxl, nxr;
    long long lazy;
    long long sum;
} tree[(MAX<<1)];
long long Built(RMQ* point) {
    point->lazy = 0;
    if ((point->r-point->l) == 1) {
        point->nxl = 0, point->nxr = 0;
        scanf("%lld", &(point->sum));
        return point->sum;
    }
    unsigned int n = 1;
    while (n < (point->r-point->l)) n <<= 1;
    point->nxl = ++ITOR;
    point->nxr = ++ITOR;
    tree[point->nxl].l = point->l, tree[point->nxl].r = point->l + (n>>1);
    tree[point->nxr].l = point->l + (n>>1), tree[point->nxr].r = point->r;
    point->sum = (Built(&tree[point->nxl]) + Built(&tree[point->nxr]));
    return point->sum;
}
void init(){
    ITOR = 1;
    memset(&tree[0], 0, sizeof(tree[0]));
    tree[1].l = 0, tree[1].r = n;
    tree[1].lazy = 0;
    Built(&tree[1]);
}
long long search(RMQ* now, unsigned int l, unsigned int r) {
    if(now->l == now->r) 
        return 0;
    if (l == now->l && r == now->r) 
        return (now->sum + (long long)now->lazy * (r-l));
    now->sum += ((long long) now->lazy * (now->r-now->l));
    tree[now->nxl].lazy += now->lazy, tree[now->nxr].lazy += now->lazy;
    now->lazy = 0;
    if (l >= tree[now->nxl].r)
        return search(&tree[now->nxr], l, r);
    if (r <= tree[now->nxr].l) 
        return search(&tree[now->nxl], l, r); 
    return (search(&tree[now->nxl], l, tree[now->nxl].r) + 
            search(&tree[now->nxr], tree[now->nxr].l, r));
}
long long add(RMQ* now, unsigned int l, unsigned int r, long long lazy) {
    if (now->l == now->r) return 0;
    if (l == now->l && r == now->r) {
        now->lazy += lazy;
        return (now->sum + now->lazy * (r-l));
    }
    now->sum += (long long)now->lazy * (now->r - now->l);
    now->sum += lazy * (r-l);
    tree[now->nxl].lazy += now->lazy, tree[now->nxr].lazy += now->lazy;
    now->lazy = 0;
    if (r <= tree[now->nxr].l)
        return add(&tree[now->nxl], l, r, lazy);
    if (l >= tree[now->nxr].l)
        return add(&tree[now->nxr], l, r, lazy);
    return (add(&tree[now->nxl], l, tree[now->nxl].r, lazy) + 
            add(&tree[now->nxr], tree[now->nxr].l, r, lazy));

}
void judge(){
    init();
    for (int i = 0; i < q; ++i) {
        c = 0;
        while (c != 'Q' && c != 'C')
            c = getchar();
        if (c == 'Q') {
            scanf("%u%u", &sl, &sr);
            printf("%lld\n", search(&tree[1], sl-1, sr));
        }
        if (c == 'C') {
            scanf("%u%u%lld", &sl, &sr, &sn);
            add(&tree[1], sl-1, sr, sn);
        }
    }
}
int main() {
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
    while (scanf("%u%u", &n, &q) == 2) {
        judge();
    }
    cerr << "teme: " << (long long)clock()*1000/CLOCKS_PER_SEC << " ms " << endl;
    return 0;
}
/*************************************************************************************
void debug_bfs() {
    queue<RMQ> que;
    que.push(tree[1]);
    while (que.size()) {
        RMQ now = que.front();
        que.pop();
        if (now.nxl)
            que.push(tree[now.nxl]);
        if (now.nxr)
            que.push(tree[now.nxr]);
        cout << "now.l = " << now.l << ", now.r = " << now.r << endl;
        cout << "now.nxl = " << now.nxl << ", nxr = " << now.nxr << endl;
        cout << "now.sum = " << now.sum << ", now.lazy = " << now.lazy << endl;
        cout << endl;
    }
}
****************************************************************************************
void debug() {
    for (int i = 0; i <= ITOR; ++i) {
        cout << "ITOR = " << i << endl;
        RMQ now = tree[i];
        cout << "\tnow.l = " << tree[i].l << ", now.r = " << tree[i].r << endl;
        cout << "\tnow.nxl = " << tree[i].nxl << ", nxr = " << tree[i].nxr << endl;
        cout << "\tnow.sum = " << tree[i].sum << ", now.lazy = " << tree[i].lazy << endl;
        cout << endl;
    }
}
*************************************************************************************/

目测是写挫了, 大概还能优化出 2 到 3 倍的常数, 开始没想到 iostream 和 stdio 会差出四倍来, 一度卡到10倍常数…..
ps. 然而要来同学1700ms的代码本地对拍发现还是我的块233333, 可能是poj老掉牙的优化的问题吧.

随机数生成

#include <stdio.h>
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;

int n, q;

int main() {
    freopen("in.in", "w", stdout);
    srand(time(NULL));
    for (int i = 0; i < 100000; ++i) {
        n = 0, q = 0;
        while (n < 1) n = rand() % 300;
        while (!q) q = rand() % 200;
        printf("%d %d\n", n, q);
        for (int i = 0; i < n; ++i)
            cout << (int)(rand() % 30000) * ((rand()%2) ? 1 : -1) << " ";
        cout << endl;
        for (int i = 0; i < q-1; ++i) {
            int l = 0, r = 0;
            while (!l) l = rand() % (n+1) ;
            while (r < l) r = rand() % (n+1);
        if (rand()% 3)
                printf("C %d %d %d\n", l, r, (rand() % 30000) * ((rand()%2) ? 1 : -1));
            else 
                printf("Q %d %d\n", l, r);
        }
        printf("Q 1 1\n");
    }
    return 0;
}

2017-08-30

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值