[关闭]
@iamtts 2017-01-21T12:57:07.000000Z 字数 2741 阅读 987

寒假集训队训练题 线段树+树状数组

A - 敌兵布阵

题目大意:对区间中单个元素进行加减操作,并求区间和

解题思路:树状数组的标准模板

AC代码:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <string>
  4. #include <iostream>
  5. #include <cstring>
  6. #include <cmath>
  7. using namespace std;
  8. int bit[50001];
  9. int N;
  10. int sum(int x)
  11. {
  12. int sum=0;
  13. while(x>0)
  14. {
  15. sum+=bit[x];
  16. x-=x&-x;
  17. }
  18. return sum;
  19. }
  20. void add(int x,int index)
  21. {
  22. while(index<=N)
  23. {
  24. bit[index]+=x;
  25. index+=index&-index;
  26. }
  27. }
  28. void gets_(char a[])
  29. {
  30. int i=0;
  31. while((a[i]=getchar())!=' ' && a[i]!='\n')
  32. i++;
  33. }
  34. int main()
  35. {
  36. int t,num=0,i,a,b,temp;
  37. char ch[10];
  38. scanf("%d",&t);
  39. while(t--)
  40. {
  41. fill(bit,bit+50001,0);
  42. scanf("%d",&N);
  43. for(i=1;i<=N;i++)
  44. {
  45. scanf("%d",&temp);
  46. add(temp,i);
  47. //printf("%d ",bit[i]);
  48. }
  49. //printf("bit[4]=%d\n",bit[4]);
  50. printf("Case %d:\n",++num);
  51. while(true)
  52. {
  53. getchar();
  54. gets_(ch);
  55. if(ch[0]=='Q')
  56. {
  57. scanf("%d%d",&a,&b);
  58. printf("%d\n",sum(b)-sum(a-1));
  59. continue;
  60. }
  61. else if(ch[0]=='A')
  62. {
  63. scanf("%d%d",&a,&b);
  64. add(b,a);
  65. continue;
  66. }
  67. else if(ch[0]=='S')
  68. {
  69. scanf("%d%d",&a,&b);
  70. add(-b,a);
  71. continue;
  72. }
  73. else break;
  74. }
  75. }
  76. return 0;
  77. }

B - Color the ball

题目大意:对区间中每一个元素进行加1操作,多组操作后输出所有元素

解题思路:树状数组对每组区间首元素进行加1,这样求sum(i)就可以得到第i个元素的值了

AC代码:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <string>
  4. #include <iostream>
  5. #include <cstring>
  6. #include <cmath>
  7. using namespace std;
  8. int bit[100001];
  9. int N;
  10. int sum(int x)
  11. {
  12. int sum=0;
  13. while(x>0)
  14. {
  15. sum+=bit[x];
  16. x-=x&-x;
  17. }
  18. return sum;
  19. }
  20. void add(int x,int index)
  21. {
  22. while(index<=N)
  23. {
  24. bit[index]+=x;
  25. index+=index&-index;
  26. }
  27. }
  28. int main()
  29. {
  30. int i,a,b;
  31. while(scanf("%d",&N),N)
  32. {
  33. fill(bit,bit+100001,0);
  34. for (i=0;i<N;i++)
  35. {
  36. scanf("%d%d",&a,&b);
  37. add(1,a);
  38. add(-1,b+1);
  39. }
  40. for (i=1;i<N;i++)
  41. printf("%d ",sum(i));
  42. printf("%d",sum(N));
  43. printf("\n");
  44. }
  45. return 0;
  46. }

C - Mayor's posters

题目大意:存在先后顺序的对区间进行覆盖操作,求最后可以看见多少种不同的覆盖

解题思路:每组操作的区间很大,所以进行离散化,然后是对离散化后的操作构造线段树,进行区间的更新,对应操作区间赋值为操作次数,建立bool数组记录不同的操作

AC代码:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <string>
  4. #include <iostream>
  5. #include <cstring>
  6. #include <cmath>
  7. #define MAXN 10005
  8. using namespace std;
  9. int li[MAXN],ri[MAXN],x[MAXN<<2],st[MAXN<<4];
  10. int N,ans;
  11. bool all[MAXN<<2];
  12. void pushdown(int k)
  13. {
  14. st[k<<1]=st[k<<1|1]=st[k];
  15. st[k]=-1;
  16. }
  17. void update(int l,int r,int L,int R,int k,int c)
  18. {
  19. if (l<=L && R<=r)
  20. {
  21. st[k]=c;
  22. return;
  23. }
  24. int m_=(L+R)>>1;
  25. if (st[k]!=-1) pushdown(k);
  26. if (m_>=l) update(l,r,L,m_,k<<1,c);
  27. if (m_<r) update(l,r,m_+1,R,k<<1|1,c);
  28. }
  29. void query(int l,int r,int k)
  30. {
  31. if (r==l)
  32. {
  33. if (st[k]!=-1 && !all[st[k]])
  34. {
  35. ans++;
  36. all[st[k]]=true;
  37. }
  38. return;
  39. }
  40. if (st[k]!=-1) pushdown(k);
  41. int m_=(l+r)>>1;
  42. query(l,m_,k<<1);
  43. query(m_+1,r,k<<1|1);
  44. }
  45. int main()
  46. {
  47. int i,a,b,t,m,num=0;
  48. scanf("%d",&t);
  49. while(t--)
  50. {
  51. fill(all,all+(MAXN<<2),false);
  52. fill(st,st+(MAXN<<4),-1);
  53. num=0;
  54. scanf("%d",&N);
  55. for (i=0; i<N; i++)
  56. {
  57. scanf("%d%d",&li[i],&ri[i]);
  58. x[++num]=li[i];
  59. x[++num]=ri[i];
  60. }
  61. sort(x+1,x+num+1);
  62. //ÀëÉ¢»¯
  63. for (m=1,i=2; i<=num; i++)
  64. if (x[i]!=x[i-1]) x[++m]=x[i];
  65. for(i=m; i>1; i--)
  66. if (x[i]-x[i-1]>1) x[++m]=x[i]-1;
  67. sort(x+1,x+m+1);
  68. for (i=0; i<N; i++)
  69. {
  70. int *p=&x[0];
  71. int l=lower_bound(x+1,x+m+1,li[i])-p;
  72. int r=lower_bound(x+1,x+m+1,ri[i])-p;
  73. update(l,r,1,m,1,i+1);
  74. }
  75. ans=0;
  76. query(1,m,1);
  77. printf("%d\n",ans);
  78. }
  79. return 0;
  80. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注