hdu1166 敌兵布阵

来源:互联网 发布:mac版photoshop cc2015 编辑:程序博客网 时间:2024/05/01 14:20

题意要求支持三个操作。

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;}


0 0