线段树成段更新的裸题。。。。。因为没强制在线,用前缀和水了一发 700ms
http://acm.hdu.edu.cn/showproblem.php?pid=1556
用线段树水了一发。。。1600ms。。。
区间线段树 和 前缀和数组记录两种方法都可以实现 单点/区间更新(logn)、单点/区间查询(logn)
不同就是 前者是 在线算法,即可以边更新边查询(logn),后者是离线算法,即只能先把全部更新预先做完,最后再查询
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <cstdio> #include <algorithm> #include <iostream> #include<stdlib.h> #include <queue> #include <set> #include <vector> #define MAX 100005 #define inf 0x3f3f3f3f using namespace std; int vis[MAX]; int main() { int N,i,a,b; while(scanf("%d",&N)!=EOF) { if (!N) break; for (i=1;i<=N;i++) { scanf("%d%d",&a,&b); vis[a]++; vis[b+1]--; } for (i=1;i<=N;i++) { vis[i]+=vis[i-1]; } for (i=1;i<=N;i++) { if (i!=1) printf(" "); printf("%d",vis[i]); } printf("\n"); for (i=1;i<=N+1;i++) { vis[i]=0; } } return 0; }
线段树 成段更新:
</pre> <pre name="code" class="cpp">#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> #include <set> #include <vector> using namespace std; const int N = 4*100005 ; int sum[N], add[N] ; void pushDown(int i, int l, int r) //把i节点的延迟标记传递到左右儿子节点 { if(add[i] != 0) { int mid = (l + r) >> 1; add[i << 1] += add[i]; sum[i << 1] += (mid - l + 1) * add[i]; //[l, mid]代表左儿子区间 add[i << 1 | 1] += add[i]; sum[i << 1 | 1] += (r - mid) * add[i]; //[mid + 1, r]代表右儿子区间 add[i] = 0; } } void update(int i, int l, int r, int ql, int qr, int val) //更新区间为qlqr,当前区间为l,r,代表当前区间和的节点为i,更新值为val, { if(l > qr || ql > r) //更新区间不在当前区间内 return ; if(l >= ql && r <= qr) //要更新的区间把当前区间完全包括,则把当前整个区间+val,然后返回上一层 { sum[i] += (r - l + 1) * val; add[i] += val; return ; } pushDown(i, l, r); //如果上面没reutrn 表示要往左右儿子区间查询,所以把延迟标记放下去 int mid = (l + r) >> 1; update(i << 1, l, mid, ql, qr, val); update(i << 1 | 1, mid + 1, r, ql, qr, val); sum[i] = sum[i << 1] + sum[i << 1 | 1]; } int query(int i, int l, int r, int ql, int qr) //查询区间为qlqr,当前区间为l,r,代表当前区间和的节点为i { if(l > qr || ql > r) return 0; if(l >= ql && r <= qr) return sum[i]; pushDown(i, l, r); //同update int mid =( l + r) >> 1; return query(i << 1, l, mid, ql, qr) + query(i << 1 | 1, mid + 1, r, ql, qr); } int main() { int n ,a,b,i; while( scanf("%d", &n)!=EOF) { memset(add,0,sizeof(add)); memset(sum,0,sizeof(sum)); if (!n) break; for( i = 1; i <= n; i++) update(1, 1, n, i, i,0); for( i = 1; i <= n; i++) { scanf("%d %d",&a,&b); update(1, 1, n, a, b, 1); } for( i = 1; i <= n; i++) { if (i!=1) printf(" "); printf("%d",query(1, 1,n,i,i) ); } printf("\n"); } return 0; }