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