@wwwqeqeqeqe
2017-03-27T11:54:33.000000Z
字数 2451
阅读 954
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);elseadd(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);elseadd(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);elseQuery(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;}