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

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

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值