您的位置:首页 > 其它

HDU 1166 敌兵布阵

2017-04-14 19:03 204 查看


敌兵布阵

题目链接:点击打开链接

题目和本博客里之前的题目没什么区别,都是典型的树状数组增删改查。

代码如下:

#include<stdio.h>
#include<string.h>
#define MAXN 50005
int tree[MAXN];
int data[MAXN];
void add(int x,int num)
{
for(int i=x;i<MAXN;i+=i&(-i))
tree[i]+=num;
}
int read(int x)
{
int sum=0;
for(int i=x;i>0;i-=i&(-i))
sum+=tree[i];
return sum;
}
void A()
{
int x,num;
scanf("%d%d",&x,&num);
x++;
add(x,num);
}
void S()
{
int x,num;
scanf("%d%d",&x,&num);
x++;
add(x,-num);
}
void Q()
{
int x,y;
scanf("%d%d",&x,&y);
x++;y++;
int sum=read(y)-read(x-1);
printf("%d\n",sum);
}
int main()
{
int t,n;
int index=1;
char str[10];
scanf("%d",&t);
while(t--)
{
memset(tree,0,sizeof(tree));
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&data[i]);
add(i+2,data[i]);
}
printf("Case %d:\n",index++);
while(scanf("%s",&str))
{
if(str[0]=='A')
A();
else if(str[0]=='S')
S();
else if(str[0]=='Q')
Q();
else if(str[0]=='E')
break;
}
}
return 0;
}

2017/9/27 加入线段树模板代码:

#include<iostream>
#include<cstdio>
using namespace std;
//(0)定义
#define maxn 100007 //元素的总个数
#define ls,l,m,rt<<1
#define rs m+1,r,rt<<1|1

void PushDown(int rt,int ln,int rn);//声明
void Update(int L,int C,int l,int r,int rt);
int Sum[maxn<<2],Add[maxn<<2]; //Sum构成线段树,Add为懒惰数组
int n,A[maxn]; //原数组下标[1,n];
//(1)建树
void PushUp(int rt) {Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];}
void Build(int l,int r,int rt)//l,r表示当前结点区间,rt当前节点编号
{
if(l==r){
Sum[rt]=A[l];
return ;
}
int m=(l+r)>>1;
Build(l,m,rt<<1);
Build(m+1,r,rt<<1|1);
PushUp(rt);
}
//(2)点修改
void Update(int L,int C,int l,int r,int rt)//l,r表示当前节点区间,rt表示当前节点编号
{
if(l==r){
Sum[rt]+=C;
return ;
}
int m=(l+r)>>1;
if(L<=m) Update(L,C,l,m,rt<<1);
else Update(L,C,m+1,r,rt<<1|1);
PushUp(rt);
}
void Update(int L,int R,int C,int l,int r,int rt)
{
if(L<=l && r<=R){
Sum[rt]+=C*(r-l+1);
Add[rt]+=C;
return ;
}
int m=(l+r)>>1;
PushDown(rt,m-l+1,r-m);
if(L<=m) Update(L,R,C,l,m,rt<<1);
if(R>m) Update(L,R,C,m+1,r,rt<<1|1);
PushUp(rt);
}
void PushDown(int rt,int ln,int rn)
{//ln,rn为左子树,右子树的数字数量。
if(Add[rt])
{//下推标记
Add[rt<<1]+=Add[rt];
Add[rt<<1|1]=Add[rt];
Sum[rt<<1]+=Add[rt]*ln;
Sum[rt<<1|1]+=Add[rt]*rn;
Add[rt]=0; //清除标记
}
}
int Query(int L,int R,int l,int r,int rt){//L,R表示操作区间,l,r表示当前节点区间,rt表示当前节点编号
if(L <= l && r <= R){
//在区间内,直接返回
return Sum[rt];
}
int m=(l+r)>>1;
//下推标记,否则Sum可能不正确
PushDown(rt,m-l+1,r-m);
//累计答案
int ANS=0;
if(L <= m) ANS+=Query(L,R,l,m,rt<<1);
if(R > m) ANS+=Query(L,R,m+1,r,rt<<1|1);
return ANS;
}

int main()
{
int L,R,C,n,t;
char str[15];
int l,r,inde;
inde=0;
scanf("%d",&t);
while(t--)
{
printf("Case %d:\n",++inde);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&A[i]);
Build(1,n,1);//建树
while(1)
{
scanf("%s",&str);
if(str[0]=='E')
break;
else{
scanf("%d%d",&l,&r);
if(str[0]=='A')
Update(l,r,1,n,1);//点修改
else if(str[0]=='S')
Update(l,-r,1,n,1);//点修改
else{
int ANS=Query(l,r,1,n,1);//区间查询
printf("%d\n",ANS);
}
}
}
}
// Build(1,n,1);//建树
// Update(L,C,1,n,1);//点修改
// Update(L,R,C,1,n,1);//区间修改
// int ANS=Query(L,R,1,n,1);//区间查询

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: