您的位置:首页 > 其它

HDU 1166 敌兵布阵 (线段树 单点更新)

2014-08-04 17:23 375 查看
题目链接

线段树掌握的很差,打算从头从最简单的开始刷一波, 嗯。。就从这个题开始吧!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#include <algorithm>
const int maxn = 50000+10;
using namespace std;
int a[maxn], n;
struct line
{
int l, r, val;
}tr[maxn<<2];

void build(int o, int l, int r)
{
tr[o].l = l; tr[o].r = r;
if(l == r)
{
tr[o].val = a[l];
return;
}
int mid = (l+r)>>1;
build(2*o, l, mid);
build(2*o+1, mid+1, r);
tr[o].val = tr[2*o].val+tr[2*o+1].val;
}
int query(int o, int l, int r)
{
if(tr[o].l==l && tr[o].r==r)
return tr[o].val;
int mid = (tr[o].l+tr[o].r)>>1;
if(r <= mid) query(2*o, l, r);
else if(l > mid) query(2*o+1, l, r);
else
return (query(2*o, l, mid)+query(2*o+1, mid+1, r));
}
void update(int o, int p, int add)
{
if(tr[o].l==tr[o].r&&tr[o].l==p)
{
tr[o].val += add;
return;
}
int mid = (tr[o].l+tr[o].r)>>1;
if(p<=mid) update(2*o, p, add);
else update(2*o+1, p, add);
tr[o].val = tr[2*o].val+tr[2*o+1].val;
}
int main()
{
int t, i, ca = 1;
int p, add, l, r;
char s[20];
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(i = 1; i <= n; i++)
scanf("%d", &a[i]);
printf("Case %d:\n", ca++);

build(1, 1, n);
while(~scanf("%s", s))
{
if(strcmp(s, "End")==0) break;
if(s[0]=='Q')
{
scanf("%d%d", &l, &r);
printf("%d\n", query(1, l, r));
}
if(s[0]=='A')
{
scanf("%d%d", &p, &add);
update(1, p, add);
}
if(s[0]=='S')
{
scanf("%d%d", &p, &add);
update(1, p, -add);
}
}
}
return 0;
}


注释的代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#include <algorithm>
const int maxn = 50000+10;
using namespace std;
int a[maxn], n;
struct line
{
int l, r, val;   //val表示该区间的和
}tr[maxn<<2];

void build(int o, int l, int r) //o代表当前节点编号
{
tr[o].l = l; tr[o].r = r;
if(l == r)
{
tr[o].val = a[l];
return;
}
int mid = (l+r)>>1;
build(2*o, l, mid);
build(2*o+1, mid+1, r);
tr[o].val = tr[2*o].val+tr[2*o+1].val;  //建树把值从下往上加起来
}
int query(int o, int l, int r)  //求l到r的和
{
if(tr[o].l==l && tr[o].r==r) //节点的区间吻合返回
return tr[o].val;
int mid = (tr[o].l+tr[o].r)>>1;
if(r <= mid) query(2*o, l, r);
else if(l > mid) query(2*o+1, l, r);
else
return (query(2*o, l, mid)+query(2*o+1, mid+1, r)); //横跨了区间
}
void update(int o, int p, int add) //对p节点增加add
{
if(tr[o].l==tr[o].r&&tr[o].l==p)
{
tr[o].val += add;
return;
}
int mid = (tr[o].l+tr[o].r)>>1;
if(p<=mid) update(2*o, p, add);
else update(2*o+1, p, add);
tr[o].val = tr[2*o].val+tr[2*o+1].val;  //找到值以后的更新
}
int main()
{
int t, i, ca = 1;
int p, add, l, r;
char s[20];
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(i = 1; i <= n; i++)
scanf("%d", &a[i]);
printf("Case %d:\n", ca++);

build(1, 1, n);
while(~scanf("%s", s))
{
if(strcmp(s, "End")==0) break;
if(s[0]=='Q')
{
scanf("%d%d", &l, &r);
printf("%d\n", query(1, l, r));
}
if(s[0]=='A')
{
scanf("%d%d", &p, &add);
update(1, p, add);
}
if(s[0]=='S')
{
scanf("%d%d", &p, &add);
update(1, p, -add);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: