@wwwqeqeqeqe
2017-03-27T19:54:33.000000Z
字数 2451
阅读 820
A
题目大意
先输入一个数T,表示有T组数据。在每组数据中,第一行给出一个数N,表示有N个工兵营地。接着输入N个数,表示第i个工兵营地里有ai个人,然后输入命令,命令的种类一共有四种,分别表示增加,减少人数,查询一个范围内工兵营地的总人数,以及一个结束语句。让你输出每个查询语句中工兵营地的总人数。
解题思路
裸的线段树模板,减少人数可以表示为增加负数的人数。
AC代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1e5+5;
struct node
{
int l,r,val;
};
int T,N,a[maxn];
char s[15];
node tree[maxn*4];
void pushup(int x)
{
tree[x].val=tree[x<<1].val+tree[x<<1|1].val;
}
void build(int l,int r,int x,int a[])
{
tree[x].l=l;
tree[x].r=r;
if(l==r)
tree[x].val=a[l];
else
{
int mid=(l+r)>>1;
build(l,mid,x<<1,a);
build(mid+1,r,x<<1|1,a);
pushup(x);
}
}
void add(int pos,int v,int x)
{
if(tree[x].l==tree[x].r)
tree[x].val+=v;
else
{
int mid=(tree[x].l+tree[x].r)>>1;
if(pos<=mid)
add(pos,v,x<<1);
else
add(pos,v,x<<1|1);
pushup(x);
}
}
int Query(int l,int r,int x)
{
if(tree[x].l>=l&&tree[x].r<=r)
return tree[x].val;
int ans=0;
int mid=(tree[x].l+tree[x].r)>>1;
if(l<=mid)
ans+=Query(l,r,x<<1);
if(mid<r)
ans+=Query(l,r,x<<1|1);
return ans;
}
int main()
{
int z,y;
scanf("%d",&T);
int casee=0;
while(T--)
{
memset(tree,0,sizeof(tree));
memset(a,0,sizeof(a));
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%d",&a[i]);
build(1,N,1,a);
printf("Case %d:\n",++casee);
while(~scanf("%s",s))
{
if(s[0]=='E')
break;
else if(s[0]=='Q')
{
scanf("%d%d",&z,&y);
printf("%d\n",Query(z,y,1));
}
else if(s[0]=='A')
{
scanf("%d%d",&z,&y);
add(z,y,1);
}
else if(s[0]=='S')
{
scanf("%d%d",&z,&y);
add(z,-y,1);
}
}
}
return 0;
}
B
题目大意
先给你N个数,表示气球的总数,在接下来的若干行中,输入两个数a和b,表示从第a个气球到第b个气球每个气球上了一次颜色,最后输出每个气球一共被上了几次颜色。
解题思路
可以通过线段树解决这个问题。在进行上色的过程中,通过判断左右边界是否相等来进行数据增加记录,在mid左边就查找x*2,右边的就查找x*2+1,最后查找的过程同样如此,最后找到每个气球被上色的数量。
AC代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1e5+5;
struct node
{
int l,r,val;
};
node tree[maxn*4];
int N,t;
void build(int l,int r,int x)
{
tree[x].l=l;
tree[x].r=r;
tree[x].val=0;
if(l!=r)
{
int mid=(l+r)>>1;
build(l,mid,x<<1);
build(mid+1,r,x<<1|1);
}
}
void add(int l,int r,int x)
{
if(tree[x].l==l&&tree[x].r==r)
tree[x].val++;
else
{
int mid=(tree[x].l+tree[x].r)>>1;
if(l<=mid&&r>mid)
{
add(l,mid,x<<1);
add(mid+1,r,x<<1|1);
}
else
{
if(r<=mid)
add(l,r,x<<1);
else
add(l,r,x<<1|1);
}
}
}
int Query(int pos,int x)
{
t+=tree[x].val;
if(tree[x].l!=tree[x].r)
{
int mid=tree[x].l+tree[x].r>>1;
if(pos<=mid)
Query(pos,x<<1);
else
Query(pos,x<<1|1);
}
return t;
}
int main()
{
int a,b;
while(~scanf("%d",&N)&&N)
{
memset(tree,0,sizeof(tree));
build(1,N,1);
for(int i=0; i<N; i++)
{
scanf("%d%d",&a,&b);
add(a,b,1);
}
for(int i=1;i<N;i++)
{
t=0;
printf("%d ",Query(i,1));
}
t=0;
printf("%d\n",Query(N,1));
}
return 0;
}