HDU 1166 敌兵布阵(线段树&树状数组)

来源:互联网 发布:windows键怎么关闭 编辑:程序博客网 时间:2024/05/22 10:46

题目:HDU 1166 敌兵布阵

线段树模板题同时也是树状数组模板题,两种解法:

线段树:

//Must so#include<bits/stdc++.h>#define mem(a,x) memset(a,x,sizeof(a))#define sqrt(n) sqrt((double)n)#define pow(a,b) pow((double)a,(int)b)#define inf 1<<29#define NN 50004using namespace std;const double PI = acos(-1.0);typedef long long LL;struct Node{    int l,r,v;}q[4*NN];void buildtree(int i,int l,int r){    q[i].l = l,q[i].r = r;    if (l == r)    {        scanf("%d",&q[i].v);        return ;    }    int mid = (l+r)/2;    buildtree(i<<1,l,mid);    buildtree((i<<1)+1,mid+1,r);    q[i].v = q[i<<1].v + q[(i<<1)+1].v;}void Add(int i,int a,int b){    if (q[i].l == q[i].r &&q[i].l == a)    {        q[i].v += b;        return ;    }    int mid = (q[i].l+q[i].r)/2;    if (a <= mid) Add(i<<1,a,b);    else Add((i<<1)+1,a,b);    q[i].v += b;}int query(int i,int l,int r){    if (l == q[i].l&&r == q[i].r)    {        return q[i].v;    }    int mid = (q[i].l+q[i].r)/2;    if (r <= mid) return query(i<<1,l,r);    else if (l > mid) return query((i<<1)+1,l,r);    else return query(i<<1,l,mid)+query((i<<1)+1,mid+1,r);}int main(){    int T;    scanf("%d",&T);    int kas = 1;    while (T--)    {        printf("Case %d:\n",kas++);        int n;        scanf("%d",&n);        buildtree(1,1,n);        string s;        while (cin>>s)        {            if (s == "End") break;            int a,b;            scanf("%d%d",&a,&b);            if (s == "Query")            {                printf("%d\n",query(1,a,b));            }            else if (s == "Add")            {                Add(1,a,b);            }            else            {                Add(1,a,-b);            }        }    }    return 0;}

这是本渣第一道线段树的题,表示对移位运算符的优先级非常不满


树状数组:

#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<queue>#include<cmath>#include<stdlib.h>#include<cctype>#include<map>#define mem(a,x) memset(a,x,sizeof(a))#define esp 1e-8using namespace std;typedef long long ll;const int N = 50000;int c[N+5],n;int lowbit(int x){    return x&(-x);}void Add(int i,int v)//将第i个元素的值修改成v{    while (i <= n)    {        c[i] += v;        i += lowbit(i);    }}int Sun(int i)//求前i项和{    int s = 0;    while (i > 0)    {        s += c[i];        i -= lowbit(i);    }    return s;}int main(){    int T;scanf("%d",&T);    int kas = 0;    while (T--)    {        scanf("%d",&n);        mem(c,0);        for (int i = 1,v;i <= n;++i)        {            scanf("%d",&v);            Add(i,v);        }        printf("Case %d:\n",++kas);        string s;        while (cin>>s)        {            if (s == "End") break;            int x,y;scanf("%d %d",&x,&y);            if (s == "Add")            {                Add(x,y);            }            else if  (s == "Sub")            {                Add(x,-y);            }            else printf("%d\n",Sun(y)-Sun(x-1));        }    }    return 0;}

树状数组代码更短,但是其实个人对于线段树的理解更深,不过某大神说算法竞赛优先选择用树状数组。。。

大神给的成神之路:点我开启成神之路~~~

0 0
原创粉丝点击