hdu 1166 敌兵布阵

简单线段树,提供两种建树的方法:

 对于query(x, y):

int query(int root, int Std, int End)
{
    int Lans = 0;
    int Rans = 0;
    if(Std <= st[root].st && st[root].ed <= End)
        return st[root].sum;
    else{
        int mid = (st[root].st+st[root].ed)/2;
        if(Std <= mid) Lans = query(root*2, Std, End);
        if(mid < End) Rans = query(root*2+1, Std, End);
        return Lans+Rans;
    }
}

这样左右递归一下竟然超时。

void query(int u,int l,int r)
{
    if(st[u].st>=l && st[u].ed<=r) {res+=st[u].sum;return;}
    int mid = (st[u].st+st[u].ed) >> 1;
    if(r <= mid) query(u<<1,l,r);
    else if(l > mid) query((u<<1)+1,l,r);
    else{
        query(u<<1, l, mid);
        query((u<<1)+1, mid+1, r);
    }
}

这样修改一下时间减少几十毫秒,但是看一下排行榜,有的人0毫秒就过了,看来我要好好学算法。

 

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>

using namespace std;

struct node{
    int st, ed;
    int sum;
}st[150000];

int a[50005];
int res;
/*
void build(int root, int l, int r)
{
    st[root].st = l;
    st[root].ed = r;
    for(int i = l; i <= r; i ++){
        st[root].sum += a[i];
    }
    if(r - l > 1){
        int mid = (l+r)/2;
        if(l < mid) build(root*2, l, mid);
        if(r > mid) build(root*2+1, mid, r);
    }

}
*/
void build(int root, int l, int r)
{
    st[root].st = l;
    st[root].ed = r;
    if(l == r) {
        st[root].sum = a[l];
        return ;
    }
    int mid = (l+r)>>1 ;
    build(root<<1, l, mid);
    build((root<<1)+1, mid+1, r);
    st[root].sum = st[root<<1].sum + st[(root<<1)+1].sum;
}

void Add(int p, int v, int root, int l, int r)
{
    int mid = (l+r)/2;
    if(l == r) st[root].sum += v;
    else{
        if(p <= mid) Add(p, v, root<<1, l, mid);
        else Add(p, v, (root<<1)+1, mid+1, r);
        st[root].sum = st[root<<1].sum + st[root*2+1].sum;
    }
}

void Sub(int p, int v, int root, int l, int r)
{
    int mid = (l+r)>>1;
    if(l == r) st[root].sum -= v;       // 找到该点
    else{
        if(p <= mid) Sub(p, v, root<<1, l, mid);     // 二叉查找
        else Sub(p, v, (root<<1)+1, mid+1, r);
        st[root].sum = st[root<<1].sum + st[(root<<1)+1].sum;   // 区间横跨两段
    }
}
/*

int query(int root, int Std, int End)
{
    int Lans = 0;
    int Rans = 0;
    int mid = (st[root].st+st[root].ed)>>1;
    if(Std <= st[root].st && st[root].ed <= End)
        return st[root].sum;
    else if(End < Mid) query(root<<1, Std, End);
        {

        if(Std <= mid) Lans = query(root*2, Std, End);
        if(mid < End) Rans = query(root*2+1, Std, End);
        return Lans+Rans;
    }
}
*/


void query(int u,int l,int r)
{
    if(st[u].st>=l && st[u].ed<=r) {res+=st[u].sum;return;}
    int mid = (st[u].st+st[u].ed) >> 1;
    if(r <= mid) query(u<<1,l,r);
    else if(l > mid) query((u<<1)+1,l,r);
    else{
        query(u<<1, l, mid);
        query((u<<1)+1, mid+1, r);
    }
}


int main()
{
    int t, n;
    string comm;
    int x, y;
    int flag = 1;
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++){
            scanf("%d", &a[i]);
        }
        build(1, 1, n);
        printf("Case %d:\n", flag ++);
        while(1){
            cin >> comm;
            if(comm == "End") break;
            else if(comm == "Query"){
                scanf("%d%d", &x, &y);
               // int ans = query(1, x, y);
               // cout << ans << endl;
                res = 0;
                query(1, x, y);
                cout << res << endl;

            }
            else if(comm == "Sub"){
                scanf("%d%d", &x, &y);
                Sub(x, y, 1, 1, n);
            }
            else if(comm == "Add"){
                scanf("%d%d", &x, &y);
                Add(x, y, 1, 1, n);
            }
        }
    }
    return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值