现在的位置: 首页 > 综合 > 正文

hdu1166 敌兵布阵

2018年12月23日 ⁄ 综合 ⁄ 共 3311字 ⁄ 字号 评论关闭

题意要求支持三个操作。

Add(i,j);           //点i处增加j

Sub(i,j);           //点i处减少j

Query(i,j);        //查询区间[i,j]的和

1、树状数组

#include <stdio.h>
#include <string.h>
typedef int LL;
const int MAXN = 50000 + 10;
int C[MAXN], n;

int lowbit(int x) {return (x&-x);}
void add(int i, int d) {for(; i <= n; i += lowbit(i)) C[i] += d;}
LL query(int i) {LL ret = 0; for(; i > 0; i -= lowbit(i)) ret += C[i]; return ret;}
int main()
{
    int T, cas, x, i, j;
    char cmd[10];
    scanf("%d",&T);
    for(cas=1; cas<=T; ++cas) {
        scanf("%d",&n);
        memset(C, 0, sizeof(int)*(n+1));
        for(i=1; i<=n; ++i) {
            scanf("%d",&x);
            add(i, x);
        }
        printf("Case %d:\n",cas);
        while(1) {
            scanf("%s",cmd);
            if(cmd[0] == 'E') break;
            scanf("%d%d",&i,&j);
            if(cmd[0] == 'A') {
                add(i, j);
            }else if(cmd[0] == 'S') {
                add(i, -j);
            }else if(cmd[0] == 'Q') {
                printf("%d\n",query(j) - query(i-1));
            }
        }
    }
    return 0;
}

2、线段树

( update:单点增减 query:区间求和 )

#include <cstdio>
#include <cstring>
using namespace std;


#define LL(x) ((x)<<1)
#define RR(x) ((x)<<1|1)
const int maxn = 55555;
struct point
{
    int l, r;
    int sum;
    int mid(){
        return (l+r)>>1;
    }
}tree[maxn*4];
int num[maxn];


void build(int rt, int l, int r) 
{
    tree[rt].l = l;
    tree[rt].r = r;
    if(tree[rt].l == tree[rt].r) {
        tree[rt].sum = num[l];
        return;
    }
    int mid = (tree[rt].l+tree[rt].r)>>1;
    build(LL(rt), l, mid);
    build(RR(rt), mid+1, r);
    tree[rt].sum = tree[LL(rt)].sum + tree[RR(rt)].sum;
}
void update(int rt, int pos, int val) 
{
    if(tree[rt].l == tree[rt].r) {
        tree[rt].sum +=val;
        return;
    }
    int mid = (tree[rt].l+tree[rt].r)>>1;
    if(pos<=mid) update(LL(rt), pos, val);
    else   update(RR(rt), pos, val);
    tree[rt].sum = tree[LL(rt)].sum + tree[RR(rt)].sum;
}


int query(int rt, int l, int r) 
{
    if(l <= tree[rt].l && r >= tree[rt].r) 
        return tree[rt].sum;
    int mid = (tree[rt].l + tree[rt].r) >> 1;
    int ret = 0;
    if(l <= mid) ret  += query(LL(rt), l, r);
    if( r > mid) ret += query(RR(rt), l, r);
    return ret;
}<span style="font-family: 'Courier New', Courier; white-space: pre-wrap;">/*如果恰好题中要求解的区间在左儿子或者右儿子中,那么直接返回其所在的节点的值,否则把左儿子和右儿子中的区间加起来返回*/</span>

int main()
{
    int T, n, i, a, b, val;
    char str[10];
    scanf("%d",&T);
    for(int cas = 1; cas<=T; ++cas) {
        scanf("%d",&n);
        for(i=1; i<=n; ++i) scanf("%d",&num[i]);
        build(1,1,n);
        printf("Case %d:\n", cas);
        while(1)
        {
            scanf("%s",str);
            if(str[0]=='E') break;
            if(str[0]=='Q'){
                scanf("%d%d",&a,&b);
                printf("%d\n",query(1,a,b));
            } 
            else if(str[0]=='A') {
                scanf("%d%d",&a,&val);
                update(1,a,val);
            }
            else if(str[0]=='S') {
                scanf("%d%d",&a,&val);
                update(1,a,-val);
            }
        }
    }
}


线段树(update: 2014.07.15)

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

const int maxn = 50000 + 5;
int SUM[maxn<<4];
int num[maxn];

void PushUp(int rt)
{
    SUM[rt] = SUM[rt<<1] + SUM[rt<<1|1];
}
void build(int rt, int l, int r)
{
    if(l == r)
    {
        SUM[rt] = num[l];
        return ;
    }
    int m = (l+r)>>1;
    build(rt<<1, l, m);
    build(rt<<1|1, m+1, r);
    PushUp(rt);
}

void update(int rt, int l, int r, int p, int v)
{
    if(l == r)
    {
        SUM[rt] += v;
        return ;
    }
    int m = (l+r)>>1;
    if(p<=m) update(rt<<1, l, m, p, v);
    if(p>m) update(rt<<1|1, m+1, r, p, v);
    PushUp(rt);
}

int query(int rt, int l, int r, int L, int R)
{
    if(L<=l && r<=R)
    {
        return SUM[rt];
    }

    int m = (l+r)>>1;
    int ret = 0;
    if(L<=m) ret += query(rt<<1, l, m, L, R);
    if(R>m)  ret += query(rt<<1|1, m+1, r, L, R);
    return ret;
}
int main()
{
    int t, i, n, a, b;
    scanf("%d", &t);
    for(int cas=1; cas<=t; ++cas)
    {
        printf("Case %d:\n", cas);
        scanf("%d", &n);
        for(i=1; i<=n; ++i) scanf("%d", &num[i]);
        build(1, 1, n);
        char cmd[10];
        while(scanf("%s", cmd))
        {
            if(cmd[0]=='E') break;
            scanf("%d%d", &a, &b);
            if(cmd[0] == 'Q')
            {
                int ret = query(1, 1, n, a, b);
                printf("%d\n", ret);
            }
            else if(cmd[0] =='S')
            {
                update(1, 1, n, a, -b);
            }
            else if(cmd[0]=='A')
            {
                update(1, 1, n, a, b);
            }
        }
    }
    return 0;
}

抱歉!评论已关闭.