您的位置:首页 > 其它

简单线段树专辑(未完待续 poj3468+hdu1698+hdu4325+hdu1394+poj2777

2014-05-10 11:41 393 查看


最近重新学的最简单的线段树,纪念一下:(时间紧张,就不写详细的解释了,程序里重要的地方会有注释

A: Poj3468  http://poj.org/problem?id=3468

成段更新,区间求和

#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 100005
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define type __int64
type m[maxn];
type sum[maxn*3];
type lazy[maxn*3];
class Segment_tree{
private: ;
public:
void PushUp( int rt ){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int num){
if(lazy[rt] != 0){
lazy[rt<<1] += lazy[rt];		sum[rt<<1] += lazy[rt] * (num-num/2);
lazy[rt<<1|1] += lazy[rt];		sum[rt<<1|1] += lazy[rt] * (num/2);
lazy[rt] = 0;
}
}
void build(int l,int r,int rt){
if(l == r){
sum[rt] = m[l];
lazy[rt] = 0;
return;
}
lazy[rt] = 0;//每个线段都要初始化,注意!
int mid = (l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int add,int l,int r,int rt){
if(L <= l && R >= r){
sum[rt]  += ((type)(add))*((type)(r-l+1));//o(≧口≦)o
lazy[rt] += add;
return ;
}
PushDown(rt,r-l+1);
int mid = (l+r)>>1;
if(L <= mid)update(L,R,add,lson);
if(R >  mid)update(L,R,add,rson);
PushUp(rt);//update之后不要忘记PushUp!
}
type query(int L,int R,int l,int r,int rt){
if(L <= l && R >= r){
return sum[rt];
}
PushDown(rt,r-l+1);
int mid = (l+r)>>1;
type ans = 0;
if(L <= mid)ans += query(L,R,lson);
if(R >  mid)ans += query(L,R,rson);
return ans;
}
};
int main()
{
int N,M,cas=0;
while(~scanf("%d",&N)){
scanf("%d",&M);
for (int i = 1; i <= N; i++)	scanf("%I64d",&m[i]);
Segment_tree tree;
tree.build(1,N,1);
char s[2]={};
int l,r,add;
while(M--){
scanf("%s",s);
if(s[0] == 'Q'){
scanf("%d %d",&l,&r);
if(l > r)swap(l,r);
printf("%I64d\n",tree.query(l,r,1,N,1));
}else if(s[0] == 'C'){
scanf("%d %d %d",&l,&r,&add);
if(l > r)swap(l,r);
tree.update(l,r,add,1,N,1);
}
}
}
return 0;
}


B: Hdu 1698  http://acm.hdu.edu.cn/showproblem.php?pid=1698

成段更新,区间求和

#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 100005
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
int m[maxn];
int sum[maxn*3];
int lazy[maxn*3];
class Segment_tree{
private: ;
public:
void PushUp( int rt ){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int num){
if(lazy[rt]){
lazy[rt<<1] = lazy[rt];			sum[rt<<1] = lazy[rt] * (num-num/2);
lazy[rt<<1|1] = lazy[rt];		sum[rt<<1|1] = lazy[rt] * (num/2);
lazy[rt] = 0;
}
}
void build(int l,int r,int rt){
if(l == r){
sum[rt] = 1;
lazy[rt] = 0;
return;
}
lazy[rt] = 0;//每个线段都要初始化,注意!
int mid = (l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int add,int l,int r,int rt){
if(L <= l && R >= r){
sum[rt]  = add*(r-l+1);
lazy[rt] = add;
return ;
}
PushDown(rt,r-l+1);
int mid = (l+r)>>1;
if(L <= mid)update(L,R,add,lson);
if(R > mid )update(L,R,add,rson);
PushUp(rt);//update之后不要忘记PushUp!
}
int query(int L,int R,int l,int r,int rt){
if(L <= l && R >= r){
return sum[rt];
}
int mid = (l+r)>>1;
int ans = 0;
if(L <= mid)ans += query(L,R,lson);
if(R >  mid)ans += query(L,R,rson);
return ans;
}
};
int main()
{
int T,N,M,cas=0;
scanf("%d",&T);
for(int i=0;i<T;i++){
scanf("%d %d",&N,&M);
//for (int i = 1; i <= N; i++)		scanf("%d",&m[i]);
Segment_tree tree;
tree.build(1,N,1);
int l,r,_new;
for (int i = 0; i < M; i++)
{
scanf("%d%d%d",&l,&r,&_new);
tree.update(l,r,_new,1,N,1);
}
printf("Case %d: The total value of the hook is %d.\n",++cas,sum[1]);
}
return 0;
}


C: Hdu4325  http://acm.hdu.edu.cn/showproblem.php?pid=4325

#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
#define maxn 400005
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define type int
type m[maxn];
type sum[maxn*3];
type lazy[maxn*3];
class Segment_tree{
private: ;
public:
void PushUp( int rt ){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int num){
if(lazy[rt] != 0){
lazy[rt<<1] += lazy[rt];		sum[rt<<1] += lazy[rt] * (num-num/2);
lazy[rt<<1|1] += lazy[rt];		sum[rt<<1|1] += lazy[rt] * (num/2);
lazy[rt] = 0;
}
}
void build(int l,int r,int rt){
if(l == r){
sum[rt] = 0;
lazy[rt] = 0;
return;
}
lazy[rt] = 0;//每个线段都要初始化,注意!
int mid = (l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int add,int l,int r,int rt){
if(L <= l && R >= r){
sum[rt]  += ((type)(add))*((type)(r-l+1));//o(≧口≦)o
lazy[rt] += add;
return ;
}
PushDown(rt,r-l+1);
int mid = (l+r)>>1;
if(L <= mid)update(L,R,add,lson);
if(R >  mid)update(L,R,add,rson);
PushUp(rt);//update之后不要忘记PushUp!
}
type query(int L,int R,int l,int r,int rt){
if(L <= l && R >= r){
return sum[rt];
}
PushDown(rt,r-l+1);
int mid = (l+r)>>1;
type ans = 0;
if(L <= mid)ans += query(L,R,lson);
if(R >  mid)ans += query(L,R,rson);
return ans;
}
};
int ne[maxn],l[maxn],r[maxn],q[maxn];
int main()
{
int T,N,M,cas=0,ind;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
scanf("%d",&M);
ind = 0;
for (int i = 1; i <= N; i++){
scanf("%d %d",&l[i],&r[i]);
ne[ind++] = l[i];
ne[ind++] = r[i];
}
for (int i = 1; i <= M; i++)
{
scanf("%d",&q[i]);
ne[ind++] = q[i];
}
//去重
sort(ne,ne+ind);
int newind = unique(ne,ne+ind) - ne;
map<int,int>mapp;
for (int i = 1; i <= newind; i++)
{
mapp[ne[i-1]] = i;//用map的去重方法,( ^_^ )不错嘛,
}
Segment_tree tree;
tree.build(1,newind,1);
for (int i = 1; i <= N; i++)
{
tree.update(mapp[l[i]],mapp[r[i]],1,1,newind,1);
}
printf("Case #%d:\n",++cas);
for (int i = 1; i <= M; i++)
{
printf("%d\n",tree.query(mapp[q[i]],mapp[q[i]],1,newind,1));
}
}
return 0;
}


E: Hdu1394  http://acm.hdu.edu.cn/showproblem.php?pid=1394

#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
#define maxn 5005
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define type int
int a[maxn];
type sum[maxn*3];
type lazy[maxn*3];
class Segment_tree{
private: ;
public:
void PushUp( int rt ){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int num){
if(lazy[rt] != 0){
lazy[rt<<1] += lazy[rt];		sum[rt<<1] += lazy[rt] * (num-num/2);
lazy[rt<<1|1] += lazy[rt];		sum[rt<<1|1] += lazy[rt] * (num/2);
lazy[rt] = 0;
}
}
void build(int l,int r,int rt){
if(l == r){
sum[rt] = 0;
lazy[rt] = 0;
return;
}
lazy[rt] = 0;//每个线段都要初始化,注意!
int mid = (l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int add,int l,int r,int rt){
if(L <= l && R >= r){
sum[rt]  += ((type)(add))*((type)(r-l+1));//o(≧口≦)o
lazy[rt] += add;
return ;
}
PushDown(rt,r-l+1);
int mid = (l+r)>>1;
if(L <= mid)update(L,R,add,lson);
if(R >  mid)update(L,R,add,rson);
PushUp(rt);//update之后不要忘记PushUp!
}
type query(int L,int R,int l,int r,int rt){
if(L <= l && R >= r){
return sum[rt];
}
PushDown(rt,r-l+1);
int mid = (l+r)>>1;
type ans = 0;
if(L <= mid)ans += query(L,R,lson);
if(R >  mid)ans += query(L,R,rson);
return ans;
}
};

int main(){
int N;
Segment_tree tree;
while(~scanf("%d",&N)){
tree.build(0,N-1,1);
int sum = 0;
for (int i = 0; i < N; i++)
{
scanf("%d",&a[i]);
sum += tree.query(a[i],N-1,0,N-1,1);//询问从a[i]到n-1一共有多少个一,即逆序数
tree.update(a[i],a[i],1,0,N-1,1);//在a[i]位置添上一。
}
int ans = sum;
//	printf("%d\n",ans);
for (int i = 0; i < N; i++)
{
sum += (-a[i] +(N-1 - a[i]));
//a[i]即是原数列中a[i]之后比a[i]小的数目,n-1-a[i]反之
ans = min(ans,sum);
}
printf("%d\n",ans);
}
return 0;
}


F: Poj2777  http://poj.org/problem?id=2777

#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
#define maxn 100005
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define type long long
#define LL long long
int a[maxn];
type sum[maxn*3];
int lazy[maxn*3];
class Segment_tree{
private: ;
public:
void PushUp( int rt ){
sum[rt] = sum[rt<<1] | sum[rt<<1|1];
}
void PushDown(int rt,int num){
if(lazy[rt] != 0){
lazy[rt<<1] = lazy[rt];		sum[rt<<1] = (1LL<<(lazy[rt]-1)) ;
lazy[rt<<1|1] = lazy[rt];	sum[rt<<1|1] = (1LL<<(lazy[rt]-1)) ;
lazy[rt] = 0;
}
}
void build(int l,int r,int rt){
if(l == r){
sum[rt] = 1;
lazy[rt] = 0;
return;
}
lazy[rt] = 0;//每个线段都要初始化,注意!
int mid = (l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int add,int l,int r,int rt){
if(L <= l && R >= r){
sum[rt]  = (1LL<<(add-1));//o(≧口≦)o
lazy[rt] = add;
return ;
}
PushDown(rt,r-l+1);
int mid = (l+r)>>1;
if(L <= mid)update(L,R,add,lson);
if(R >  mid)update(L,R,add,rson);
PushUp(rt);//update之后不要忘记PushUp!
}
type query(int L,int R,int l,int r,int rt){
if(L <= l && R >= r){
return sum[rt];
}
PushDown(rt,r-l+1);
int mid = (l+r)>>1;
type ans = 0;
if(L <= mid)ans |= query(L,R,lson);
if(R >  mid)ans |= query(L,R,rson);
return ans;
}
};
int one(LL x){
if(x == 0)return 0;
int n = 1;
while(x & (x-1)){
x = x&(x-1);
n++;
}
return n;
}
int main(){
int L,T,O;
Segment_tree tree;
int l,r,color;
LL ans = 0;
while(~scanf("%d%d%d",&L,&T,&O)){
tree.build(1,L,1);
char tmp[2]={};
while(O--){
scanf("%s",tmp);
if(tmp[0] == 'C'){
scanf("%d %d %d",&l,&r,&color);
if(l>r)swap(l,r);
tree.update(l,r,color,1,L,1);
}else if(tmp[0] == 'P'){
scanf("%d %d",&l,&r);
if(l>r)swap(l,r);
ans = tree.query(l,r,1,L,1);
//printf("%lld\n",ans);
printf("%d\n",one(ans));
}
}
}
return 0;
}

H:

成段更新求最值

#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
#define maxn 22222
//不算边界上的,所以用段做线段树
#define lson l,mid,rt<<1
#define rson mid,r,rt<<1|1
double x[maxn];
struct segment{
double l,r,h;
int bri;
void set(double a,double b,double c,int d){
l=a,r=b,h=c,bri=d;
}
bool operator <(const segment & d)const{
if(d.h == h)return bri < d.bri;//不算边界,就先加下边,后加上边
return h < d.h;
}
}s[maxn*2];
int cover[maxn<<2];
int sum[maxn<<2];
class Segment_tree{
public:
void PushUp(int rt){
sum[rt] = max(sum[rt<<1] , sum[rt<<1|1]);
}
void PushDown(int rt){
if(cover[rt]){
cover[rt<<1] += cover[rt];
sum[rt<<1] += cover[rt];
cover[rt<<1|1] += cover[rt];
sum[rt<<1|1] += cover[rt];
cover[rt] = 0;
}
}
void update(int L,int R,int add,int l,int r,int rt){
if(L<=l && r<=R){
sum[rt] += add;
cover[rt] += add;
return ;
}
PushDown(rt);
int mid = (l+r)>>1;
if(l == r-1)return ;//不加可能会死循环
if(L <= mid)update(L,R,add,lson);
if(R > mid)update(L,R,add,rson);
PushUp(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L <= l && R >= r){
return sum[rt];
}
PushDown(rt);
int mid = (l+r)>>1;
int ans = 0;
if(L <= mid)ans = max(ans,query(L,R,lson));
if(R > mid)ans = max(ans,query(L,R,rson));
return ans;
}
};
int main(){
int cas=1,n,i,j,k;
double a,b,w,h;int bri;
while(~scanf("%d %lf %lf",&n,&w,&h) && n){
for (j=1, i = 0,k=0; i < n; i++)
{
scanf("%lf %lf %d",&a,&b,&bri);
s[j++].set(a,a+w,b,bri);
s[j++].set(a,a+w,b+h,-bri);
x[k++] = a;
x[k++] = a+w;
}
//给x坐标排序去重
sort(x,x+k);
int newk = unique(x,x+k)-x;
map<double,int> mapx;
for (int i = 1; i <= newk; i++)
mapx[x[i-1]] = i;
//对线段排序
sort(s+1,s+j);

Segment_tree tree;
//tree.build(1,newk,1);
memset(sum,0,sizeof(sum));
memset(cover,0,sizeof(cover));
int ans = 0;
for (int i = 1; i < j; i++)
{
tree.update(mapx[s[i].l],mapx[s[i].r],s[i].bri,1,newk,1);
ans = max(ans,sum[1]);
}
printf("%d\n",ans);
}
return 0;
}

I:

#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
#define maxn 20005
#define lson l,mid,rt<<1
#define rson mid,r,rt<<1|1
struct segment{
int l,r,h;
int flag;
void set(int a,int b,int c,int x){
l=a,r=b,h=c;
flag = x;
}
bool operator <(const segment & d)const{
if(d.h == h)return flag > d.flag;
return h < d.h;
}
}s[maxn*2];
int x[maxn];
int cover[maxn<<2];
int sum[maxn<<2];
int num[maxn<<2];//竖线的数目
bool ld[maxn<<2],rd[maxn<<2];
class Segment_tree{
public:
void PushUp(int l,int r,int rt){
if(cover[rt]) {
sum[rt] = x[r-1] - x[l-1];
ld[rt] = rd[rt] = 1;
num[rt] = 2;
}else{
ld[rt] = ld[rt<<1];
rd[rt] = rd[rt<<1|1];
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
num[rt] = num[rt<<1] + num[rt<<1|1];
if(ld[rt<<1|1] && rd[rt<<1])//边界重合
num[rt]-=2;
}
}
void build(int l,int r,int rt){
if(l == r-1){
sum[rt] = 0;
cover[rt] = 0;
ld[rt] = rd[rt] = 0;
num[rt] = 0;
return ;
}
int mid = (l+r)>>1;
build(lson);
build(rson);
PushUp(l,r,rt);
}
void update(int L,int R,int add,int l,int r,int rt){
if(L<=l && r<=R){
cover[rt] += add;
PushUp(l,r,rt);
return ;
}
int mid = (l+r)>>1;
if(l == r-1)return;
if(L <= mid)update(L,R,add,lson);
if(R > mid)update(L,R,add,rson);
PushUp(l,r,rt);
}
};
int main(){
int cas=1,n,i,j,k;
int a,b,c,d;
while(~scanf("%d",&n) && n){
for (j=1,i=0,k=0; i < n; i++)
{
scanf("%d %d %d %d",&a,&b,&c,&d);
x[k++]=a;
x[k++]=c;
s[j++].set(a,c,b,1);
s[j++].set(a,c,d,-1);
}
sort(x,x+k);
int newk = unique(x,x+k)-x;
map<int ,int >mx;
for ( i = 1; i <= newk; i++)
mx[x[i-1]] = i;
sort(s+1,s+j);

Segment_tree tree;
tree.build(1,newk,1);
int ans = 0,pre = 0;
tree.update(mx[s[1].l],mx[s[1].r],s[1].flag,1,newk,1);
int height = 0;
for ( i = 2; i < j; i++)
{
height = s[i].h - s[i-1].h;
ans += abs(sum[1] - pre);
ans += num[1] * height;
pre = sum[1];
tree.update(mx[s[i].l],mx[s[i].r],s[i].flag,1,newk,1);
}
ans += abs(sum[1] - pre);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树基础