HDU1556-Color the ball-线段树成段更新入门题/前缀和

来源:互联网 发布:2017淘宝摇一摇在哪里 编辑:程序博客网 时间:2024/05/20 00:39

线段树成段更新的裸题。。。。。因为没强制在线,用前缀和水了一发  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 0x3f3f3f3fusing 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;}



0 0