zkw线段树详解

转载自:http://blog.csdn.net/qq_18455665/article/details/50989113

前言

  • 首先说说出处:
  • 清华大学 张昆玮(zkw) - ppt 《统计的力量》
  • 本文(辣鸡)编辑:BeiYu
  • 写这篇博客的原因: 
    1.zkw线段树非递归,效率高,代码短 
    2.网上关于zkw线段树的讲解实在是太少了 
    3.个人感觉很实用

更新日志

  • 20160327-Part 1(zkw线段树的建立)
  • 20160329-Part 2(单点操作)
  • 20160329-Part 3(区间操作)

Part 1

来说说它的构造

线段树的堆式储存

这里写图片描述

我们来转成二进制看看

这里写图片描述

小学生问题:找规律

规律是很显然的

  • 一个节点的父节点是这个数左移1,这个位运算就是低位舍弃,所有数字左移一位
  • 一个节点的子节点是这个数右移1,是左节点,右移1+1是右节点
  • 同一层的节点是依次递增的,第n层有2^(n-1)个节点
  • 最后一层有多少节点,值域就是多少(这个很重要)

有了这些规律就可以开始着手建树了

  • 查询区间[1,n]

最后一层不是2的次幂怎么办? 
开到2的次幂!后面的空间我不要了!就是这么任性! 
Build函数就这么出来了!找到不小于n的2的次幂 
直接输入叶节点的信息


 
 
  1. int n,M,q; int d[N<< 1];
  2. inline void Build(int n){
  3. for(M= 1;M<n;M<<= 1);
  4. for( int i=M+ 1;i<=M+n;i++) d[i]=in();
  5. }
建完了?当然没有!父节点还都是空的呢! 

维护父节点信息? 

倒叙访问,每个节点访问的时候它的子节点已经处理过辣!

  • 维护区间和?
for(int i=M-1;i;--i) d[i]=d[i<<1]+d[i<<1|1];
 
 
  • 维护最大值?
for(int i=M-1;i;--i) d[i]=max(d[i<<1],d[i<<1|1]);
 
 
  • 维护最小值?
for(int i=M-1;i;--i) d[i]=min(d[i<<1],d[i<<1|1]);
 
 
这样就构造出了一颗二叉树,也就是zkw线段树了! 

如果你是压行选手的话(比如我),建树的代码只需要两行。 
是不是特别Easy! 
新技能Get√

Part 2

单点操作

  • 单点修改

 
 
  1. void Change(int x,int v){
  2. d[M+x]+=v;
  3. }

只是这么简单?当然不是,跟线段树一样,我们要更新它的父节点!


 
 
  1. void Change(int x,int v){
  2. d[x=M+x]+=v;
  3. while(x) d[x>>= 1]=d[x<< 1]+d[x<< 1| 1];
  4. }

没了?没了。

  • 单点查询(差分思想,后面会用到)

把d维护的值修改一下,变成维护它与父节点的差值(为后面的RMQ问题做准备) 
建树的过程就要修改一下咯!


 
 
  1. void Build(int n){
  2. for(M= 1;M<=n+ 1;M<<= 1); for( int i=M+ 1;i<=M+n;i++) d[i]=in();
  3. for( int i=M -1;i;--i) d[i]=min(d[i<< 1],d[i<< 1| 1]),d[i<< 1]-=d[i],d[i<< 1| 1]-=d[i];
  4. }

在当前情况下的查询


 
 
  1. void Sum(int x,int res=0){
  2. while(x) res+=d[x],x>>= 1; return res;
  3. }

Part 3 

区间操作

询问区间和,把[s,t]闭区间换成(s,t)开区间来计算


 
 
  1. int Sum(int s,int t,int Ans=0){
  2. for (s=s+M -1,t=t+M+ 1;s^t^ 1;s>>= 1,t>>= 1){
  3. if(~s& 1) Ans+=d[s^ 1];
  4. if( t& 1) Ans+=d[t^ 1];
  5. } return Ans;
  6. }

  • 为什么~s&1?
  • 为什么t&1
    这里写图片描述 
    变成开区间了以后,如果s是左儿子,那么它的兄弟节点一定在区间内,同理,如果t是右儿子,那么它的兄弟节点也一定在区间内!

  • 这样计算不会重复吗?

答案是会的!所以注意迭代的出口s^t^1 
如果s,t就是兄弟节点,那么也就迭代完成了。

代码简单,即使背过也不难QuQ

  • 区间最小值

 
 
  1. void Sum(int s,int t,int L=0,int R=0){
  2. for(s=s+M -1,t=t+M+ 1;s^t^ 1;s>>= 1,t>>= 1){
  3. L+=d[s],R+=d[t];
  4. if(~s& 1) L=min(L,d[s^ 1]);
  5. if(t& 1) R=min(R,d[t^ 1]);
  6. }
  7. int res=min(L,R); while(s) res+=d[s>>= 1];
  8. }
差分! 

不要忘记最后的统计! 
还有就是建树的时候是用的最大值还是最小值,这个一定要注意,影响到差分。

  • 区间最大值


 
 
  1. void Sum(int s,int t,int L=0,int R=0){
  2. for(s=s+M -1,t=t+M+ 1;s^t^ 1;s>>= 1,t>>= 1){
  3. L+=d[s],R+=d[t];
  4. if(~s& 1) L=max(L,d[s^ 1]);
  5. if(t& 1) R=max(R,d[t^ 1]);
  6. }
  7. int res=max(L,R); while(s) res+=d[s>>= 1];
  8. }

同理。

  • 区间加法

 
 
  1. void Add(int s,int t,int v,int A=0){
  2. for(s=s+M -1,t=t+M+ 1;s^t^ 1;s>>= 1,t>>= 1){
  3. if(~s& 1) d[s^ 1]+=v; if(t& 1) d[t^ 1]+=v;
  4. A=min(d[s],d[s^ 1]);d[s]-=A,d[s^ 1]-=A,d[s>> 1]+=A;
  5. A=min(d[t],d[t^ 1]);d[t]-=A,d[t^ 1]-=A,d[t>> 1]+=A;
  6. }
  7. while(s) A=min(d[s],d[s^ 1]),d[s]-=A,d[s^ 1]-=A,d[s>>= 1]+=A;
  8. }
同样是差分!差分就是厉害QuQ

zkw线段树小试牛刀(code来自hzwer.com)


 
 
  1. #include<cstdio>
  2. #include<iostream>
  3. #define M 261244
  4. using namespace std;
  5. int tr[ 524289];
  6. void query(int s,int t)
  7. {
  8. int ans= 0;
  9. for(s=s+M -1,t=t+M+ 1;s^t^ 1;s>>= 1,t>>= 1)
  10. {
  11. if(~s& 1)ans+=tr[s^ 1];
  12. if(t& 1)ans+=tr[t^ 1];
  13. }
  14. printf( "%d\n",ans);
  15. }
  16. void change(int x,int y)
  17. {
  18. for(tr[x+=M]+=y,x>>= 1;x;x>>= 1)
  19. tr[x]=tr[x<< 1]+tr[x<< 1| 1];
  20. }
  21. int main()
  22. {
  23. int n,m,f,x,y;
  24. scanf( "%d",&n);
  25. for( int i= 1;i<=n;i++){ scanf( "%d",&x);change(i,x);}
  26. scanf( "%d",&m);
  27. for( int i= 1;i<=m;i++)
  28. {
  29. scanf( "%d%d%d",&f,&x,&y);
  30. if(f== 1)change(x,y);
  31. else query(x,y);
  32. }
  33. return 0;
  34. }

poj3468(code来自网络)


 
 
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cctype>
  4. #define N ((131072 << 1) + 10) //表示节点个数->不小于区间长度+2的最小2的正整数次幂*2+10
  5. typedef long long LL;
  6. inline int getc() {
  7. static const int L = 1 << 15;
  8. static char buf[L] , *S = buf , *T = buf;
  9. if (S == T) {
  10. T = (S = buf) + fread(buf , 1 , L , stdin);
  11. if (S == T)
  12. return EOF;
  13. }
  14. return *S++;
  15. }
  16. inline int getint() {
  17. static char c;
  18. while(! isdigit(c = getc()) && c != '-');
  19. bool sign = (c == '-');
  20. int tmp = sign ? 0 : c - '0';
  21. while( isdigit(c = getc()))
  22. tmp = (tmp << 1) + (tmp << 3) + c - '0';
  23. return sign ? -tmp : tmp;
  24. }
  25. inline char getch() {
  26. char c;
  27. while((c = getc()) != 'Q' && c != 'C');
  28. return c;
  29. }
  30. int M; //底层的节点数
  31. int dl[N] , dr[N]; //节点的左右端点
  32. LL sum[N]; //节点的区间和
  33. LL add[N]; //节点的区间加上一个数的标记
  34. #define l(x) (x<<1) //x的左儿子,利用堆的性质
  35. #define r(x) ((x<<1)|1) //x的右儿子,利用堆的性质
  36. void pushdown(int x) { //下传标记
  37. if (add[x]&&x<M) { //如果是叶子节点,显然不用下传标记(别忘了)
  38. add[l(x)] += add[x];
  39. sum[l(x)] += add[x] * (dr[l(x)] - dl[l(x)] + 1);
  40. add[r(x)] += add[x];
  41. sum[r(x)] += add[x] * (dr[r(x)] - dl[r(x)] + 1);
  42. add[x] = 0;
  43. }
  44. }
  45. int stack[ 20] , top; //栈
  46. void upd(int x) { //下传x至根节点路径上节点的标记(自上而下,用栈实现)
  47. top = 0;
  48. int tmp = x;
  49. for(; tmp ; tmp >>= 1)
  50. stack[++top] = tmp;
  51. while(top--)
  52. pushdown( stack[top]);
  53. }
  54. LL query(int tl , int tr) { //求和
  55. LL res= 0;
  56. int insl = 0, insr = 0; //两侧第一个有用节点
  57. for(tl=tl+M -1,tr=tr+M+ 1;tl^tr^ 1;tl>>= 1,tr>>= 1) {
  58. if (~tl& 1) {
  59. if (!insl)
  60. upd(insl=tl^ 1);
  61. res+=sum[tl^ 1];
  62. }
  63. if (tr& 1) {
  64. if(!insr)
  65. upd(insr=tl^ 1)
  66. res+=sum[tr^ 1];
  67. }
  68. }
  69. return res;
  70. }
  71. void modify(int tl , int tr , int val) { //修改
  72. int insl = 0, insr = 0;
  73. for(tl=tl+M -1,tr=tr+M+ 1;tl^tr^ 1;tl>>= 1,tr>>= 1) {
  74. if (~tl& 1) {
  75. if (!insl)
  76. upd(insl=tl^ 1);
  77. add[tl^ 1]+=val;
  78. sum[tl^ 1]+=(LL)val*(dr[tl^ 1]-dl[tl^ 1]+ 1);
  79. }
  80. if (tr& 1) {
  81. if (!insr)
  82. upd(insr=tr^ 1);
  83. add[tr^ 1]+=val;
  84. sum[tr^ 1]+=(LL)val*(dr[tr^ 1]-dl[tr^ 1]+ 1);
  85. }
  86. }
  87. for(insl=insl>> 1;insl;insl>>= 1) //一路update
  88. sum[insl]=sum[l(insl)]+sum[r(insl)];
  89. for(insr=insr>> 1;insr;insr>>= 1)
  90. sum[insr]=sum[l(insr)]+sum[r(insr)];
  91. }
  92. inline void swap(int &a , int &b) {
  93. int tmp = a;
  94. a = b;
  95. b = tmp;
  96. }
  97. int main() {
  98. //freopen("tt.in" , "r" , stdin);
  99. int n , ask;
  100. n = getint();
  101. ask = getint();
  102. int i;
  103. for(M = 1 ; M < (n + 2) ; M <<= 1);
  104. for(i = 1 ; i <= n ; ++i)
  105. sum[M + i] = getint() , dl[M + i] = dr[M + i] = i; //建树
  106. for(i = M - 1; i >= 1 ; --i) { //预处理节点左右端点
  107. sum[i] = sum[l(i)] + sum[r(i)];
  108. dl[i] = dl[l(i)];
  109. dr[i] = dr[r(i)];
  110. }
  111. char s;
  112. int a , b , x;
  113. while(ask--) {
  114. s = getch();
  115. if (s == 'Q') {
  116. a = getint();
  117. b = getint();
  118. if (a > b)
  119. swap(a , b);
  120. printf( "%lld\n" , query(a , b));
  121. }
  122. else {
  123. a = getint();
  124. b = getint();
  125. x = getint();
  126. if (a > b)
  127. swap(a , b);
  128. modify(a , b , x);
  129. }
  130. }
  131. return 0;
  132. }
可持久化线段树版本?!(来自http://blog.csdn.net/forget311300/article/details/44306265)


 
 
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. #include <vector>
  7. #define mp(x,y) make_pair(x,y)
  8. using namespace std;
  9. const int N = 100000;
  10. const int inf = 0x3f3f3f3f;
  11. int a[N + 10];
  12. int b[N + 10];
  13. int M;
  14. int lq, rq;
  15. vector<pair< int, int> > s[N * 22];
  16. void add(int id, int cur)
  17. {
  18. cur += M;
  19. int lat = 0;
  20. if (s[cur].size())
  21. lat = s[cur][s[cur].size() - 1].second;
  22. s[cur].push_back(mp(id, ++lat));
  23. for (cur >>= 1; cur; cur >>= 1)
  24. {
  25. int l = 0;
  26. if (s[cur << 1].size())
  27. l = s[cur << 1][s[cur << 1].size() - 1].second;
  28. int r = 0;
  29. if (s[cur << 1 | 1].size())
  30. r = s[cur << 1 | 1][s[cur << 1 | 1].size() - 1].second;
  31. s[cur].push_back(mp(id, l + r));
  32. }
  33. }
  34. int Q(int id, int k)
  35. {
  36. if (id >= M) return id - M;
  37. int l = id << 1, r = l ^ 1;
  38. int ll = lower_bound(s[l].begin(), s[l].end(), mp(lq, inf)) - s[l].begin() - 1;
  39. int rr = lower_bound(s[l].begin(), s[l].end(), mp(rq, inf)) - s[l].begin() - 1;
  40. int kk = 0;
  41. if (rr >= 0)kk = s[l][rr].second;
  42. if (ll >= 0)kk = s[l][rr].second - s[l][ll].second;
  43. if (kk < k) return Q(r, k - kk);
  44. return Q(l, k);
  45. }
  46. int main()
  47. {
  48. int n, m;
  49. while (~ scanf( "%d%d", &n, &m))
  50. {
  51. for ( int i = 0; i < n; i++)
  52. {
  53. scanf( "%d", a + i);
  54. b[i] = a[i];
  55. }
  56. sort(b, b + n);
  57. int nn = unique(b, b + n) - b;
  58. for (M = 1; M < nn; M <<= 1);
  59. for ( int i = 1; i < M + M; i++)
  60. {
  61. s[i].clear();
  62. //s[i].push_back(mp(0, 0));
  63. }
  64. for ( int i = 0; i < n; i++)
  65. {
  66. int id = lower_bound(b, b + nn, a[i]) - b;
  67. add(i + 1, id);
  68. }
  69. while (m--)
  70. {
  71. int k;
  72. scanf( "%d %d %d", &lq, &rq, &k);
  73. lq--;
  74. int x = Q( 1, k);
  75. printf( "%d\n", b[x]);
  76. }
  77. }
  78. return 0;
  79. }
完全模板?!(来自http://blog.csdn.net/forget311300/article/details/44306265)


 
 
  1. const int N = 1e5;
  2. struct node
  3. {
  4. int sum, d, v;
  5. int l, r;
  6. void init()
  7. {
  8. d = 0;
  9. v = -1;
  10. }
  11. void cb(node ls, node rs)
  12. {
  13. sum = ls.sum + rs.sum;
  14. l = ls.l, r = rs.r;
  15. }
  16. int len()
  17. {
  18. return r - l + 1;
  19. }
  20. void V(int x)
  21. {
  22. sum = len() * x;
  23. d = 0;
  24. v = x;
  25. }
  26. void D(int x)
  27. {
  28. sum += len() * x;
  29. d += x;
  30. }
  31. };
  32. struct tree
  33. {
  34. int m, h;
  35. node g[N << 2];
  36. void init(int n)
  37. {
  38. for (m = h = 1; m < n + 2; m <<= 1, h++);
  39. int i = 0;
  40. for (; i <= m; i++)
  41. {
  42. g[i].init();
  43. g[i].sum = 0;
  44. }
  45. for (; i <= m + n; i++)
  46. {
  47. g[i].init();
  48. scanf( "%d", &g[i].sum);
  49. g[i].l = g[i].r = i - m;
  50. }
  51. for (; i < m + m; i++)
  52. {
  53. g[i].init();
  54. g[i].sum = 0;
  55. g[i].l = g[i].r = i - m;
  56. }
  57. for (i = m - 1; i > 0; i--)
  58. g[i].cb(g[i << 1], g[i << 1 | 1]);
  59. }
  60. void dn(int x)
  61. {
  62. for ( int i = h - 1; i > 0; i--)
  63. {
  64. int f = x >> i;
  65. if (g[f].v != -1)
  66. {
  67. g[f << 1].V(g[f].v);
  68. g[f << 1 | 1].V(g[f].v);
  69. }
  70. if (g[f].d)
  71. {
  72. g[f << 1].D(g[f].d);
  73. g[f << 1 | 1].D(g[f].d);
  74. }
  75. g[f].v = -1;
  76. g[f].d = 0;
  77. }
  78. }
  79. void up(int x)
  80. {
  81. for (x >>= 1; x; x >>= 1)
  82. {
  83. if (g[x].v != -1) continue;
  84. int d = g[x].d;
  85. g[x].d = 0;
  86. g[x].cb(g[x << 1], g[x << 1 | 1]);
  87. g[x].D(d);
  88. }
  89. }
  90. void update(int l, int r, int x, int o)
  91. {
  92. l += m - 1, r += m + 1;
  93. dn(l), dn(r);
  94. for ( int s = l, t = r; s ^ t ^ 1; s >>= 1, t >>= 1)
  95. {
  96. if (~s & 1)
  97. {
  98. if (o)
  99. g[s ^ 1].V(x);
  100. else
  101. g[s ^ 1].D(x);
  102. }
  103. if (t & 1)
  104. {
  105. if (o)
  106. g[t ^ 1].V(x);
  107. else
  108. g[t ^ 1].D(x);
  109. }
  110. }
  111. up(l), up(r);
  112. }
  113. int Q(int l, int r)
  114. {
  115. int ans = 0;
  116. l += m - 1, r += m + 1;
  117. dn(l), dn(r);
  118. for ( int s = l, t = r; s ^ t ^ 1; s >>= 1, t >>= 1)
  119. {
  120. if (~s & 1)ans += g[s ^ 1].sum;
  121. if (t & 1)ans += g[t ^ 1].sum;
  122. }
  123. return ans;
  124. }
  125. };
二维情况(来自http://blog.csdn.net/forget311300/article/details/44306265)


 
 
  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <vector>
  6. #include <iostream>
  7. using namespace std;
  8. const int W = 1000;
  9. int m;
  10. struct tree
  11. {
  12. int d[W << 2];
  13. void o()
  14. {
  15. for ( int i = 1; i < m + m; i++)d[i] = 0;
  16. }
  17. void Xor(int l, int r)
  18. {
  19. l += m - 1, r += m + 1;
  20. for ( int s = l, t = r; s ^ t ^ 1; s >>= 1, t >>= 1)
  21. {
  22. if (~s & 1)d[s ^ 1] ^= 1;
  23. if (t & 1)d[t ^ 1] ^= 1;
  24. }
  25. }
  26. } g[W << 2];
  27. void chu()
  28. {
  29. for ( int i = 1; i < m + m; i++)
  30. g[i].o();
  31. }
  32. void Xor(int lx, int ly, int rx, int ry)
  33. {
  34. lx += m - 1, rx += m + 1;
  35. for ( int s = lx, t = rx; s ^ t ^ 1; s >>= 1, t >>= 1)
  36. {
  37. if (~s & 1)g[s ^ 1].Xor(ly, ry);
  38. if (t & 1)g[t ^ 1].Xor(ly, ry);
  39. }
  40. }
  41. int Q(int x, int y)
  42. {
  43. int ans = 0;
  44. for ( int xx = x + m; xx; xx >>= 1)
  45. {
  46. for ( int yy = y + m; yy; yy >>= 1)
  47. {
  48. ans ^= g[xx].d[yy];
  49. }
  50. }
  51. return ans;
  52. }
  53. int main()
  54. {
  55. int T;
  56. cin >> T;
  57. int fl = 0;
  58. while (T--)
  59. {
  60. if (fl)
  61. {
  62. printf( "\n");
  63. }
  64. fl = 1;
  65. int N, M;
  66. cin >> N >> M;
  67. for (m = 1; m < N + 2; m <<= 1);
  68. chu();
  69. while (M--)
  70. {
  71. char o[ 4];
  72. scanf( "%s", o);
  73. if (*o == 'Q')
  74. {
  75. int x, y;
  76. scanf( "%d%d", &x, &y);
  77. printf( "%d\n", Q(x, y));
  78. }
  79. else
  80. {
  81. int lx, ly, rx, ry;
  82. scanf( "%d%d%d%d", &lx, &ly, &rx, &ry);
  83. Xor(lx, ly, rx, ry);
  84. }
  85. }
  86. }
  87. return 0;
  88. }
非递归扫描线+离散化?!(来自http://blog.csdn.net/forget311300/article/details/44306265)


 
 
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <vector>
  6. #include <cmath>
  7. using namespace std;
  8. const int N = 111;
  9. int n;
  10. vector< double> y;
  11. struct node
  12. {
  13. double s;
  14. int c;
  15. int l, r;
  16. void chu(double ss, int cc, int ll, int rr)
  17. {
  18. s = ss;
  19. c = cc;
  20. l = ll, r = rr;
  21. }
  22. double len()
  23. {
  24. return y[r] - y[l - 1];
  25. }
  26. } g[N << 4];
  27. int M;
  28. void init(int n)
  29. {
  30. for (M = 1; M < n + 2; M <<= 1);
  31. g[M].chu( 0, 0, 1, 1);
  32. for ( int i = 1; i <= n; i++)
  33. g[i + M].chu( 0, 0, i, i);
  34. for ( int i = n + 1; i < M; i++)
  35. g[i + M].chu( 0, 0, n, n);
  36. for ( int i = M - 1; i > 0; i--)
  37. g[i].chu( 0, 0, g[i << 1].l, g[i << 1 | 1].r);
  38. }
  39. struct line
  40. {
  41. double x, yl, yr;
  42. int d;
  43. line() {}
  44. line( double x, double yl, double yr, int dd): x(x), yl(yl), yr(yr), d(dd) {}
  45. bool operator < ( const line &cc) const
  46. {
  47. return x < cc.x || (x == cc.x && d > cc.d);
  48. }
  49. };
  50. vector<line>L;
  51. void one(int x)
  52. {
  53. if (x >= M)
  54. {
  55. g[x].s = g[x].c ? g[x].len() : 0;
  56. return;
  57. }
  58. g[x].s = g[x].c ? g[x].len() : g[x << 1].s + g[x << 1 | 1].s;
  59. }
  60. void up(int x)
  61. {
  62. for (; x; x >>= 1)
  63. one(x);
  64. }
  65. void add(int l, int r, int d)
  66. {
  67. if (l > r) return;
  68. l += M - 1, r += M + 1;
  69. for ( int s = l, t = r; s ^ t ^ 1; s >>= 1, t >>= 1)
  70. {
  71. if (~s & 1)
  72. {
  73. g[s ^ 1].c += d;
  74. one(s ^ 1);
  75. }
  76. if (t & 1)
  77. {
  78. g[t ^ 1].c += d;
  79. one(t ^ 1);
  80. }
  81. }
  82. up(l);
  83. up(r);
  84. }
  85. double sol()
  86. {
  87. y.clear();
  88. L.clear();
  89. for ( int i = 0; i < n; i++)
  90. {
  91. double lx, ly, rx, ry;
  92. scanf( "%lf %lf %lf %lf", &lx, &ly, &rx, &ry);
  93. L.push_back(line(lx, ly, ry, 1));
  94. L.push_back(line(rx, ly, ry, -1));
  95. y.push_back(ly);
  96. y.push_back(ry);
  97. }
  98. sort(y.begin(), y.end());
  99. y.erase(unique(y.begin(), y.end()), y.end());
  100. init(y.size());
  101. sort(L.begin(), L.end());
  102. n = L.size() - 1;
  103. double ans = 0;
  104. for ( int i = 0; i < n; i++)
  105. {
  106. int l = upper_bound(y.begin(), y.end(), L[i].yl + 1e-8) - y.begin();
  107. int r = upper_bound(y.begin(), y.end(), L[i].yr + 1e-8) - y.begin() - 1;
  108. add(l, r, L[i].d);
  109. ans += g[ 1].s * (L[i + 1].x - L[i].x);
  110. }
  111. return ans;
  112. }
  113. int main()
  114. {
  115. int ca = 1;
  116. while ( cin >> n && n)
  117. {
  118. printf( "Test case #%d\nTotal explored area: %.2f\n\n", ca++, sol());
  119. }
  120. return 0;
  121. }


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值