POJ 4047 Garden

POJ 4047 Garden

线段树题目,很简单。需要预处理一下,树的节点中存储的元素为区间的两个端点,然后该段中最大的值,还有延迟标记。预处理的时候先求出所有长度为k的序列的长度,然后建树。具体的程序如下:开始的时候忽略了测试例子数,所以一直runtime error。抓狂

/*
ID : csuchenan
PEOG: D Garden
LANG: C++
*/

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 201000

using namespace std ;

struct Node{
	int l ;
	int r ;
	int flag ;
	int nmax ;
}node[4*MAXN] ; 

int nsum[MAXN] ;
int nval[MAXN] ;

int n ;
int m ;
int k ;

bool init() ;
void work() ;

void pushdown(int root) ;
void pushup(int root) ;
void solve(int x , int y) ;

void build(int l , int r , int c) ;
void update(int l , int r , int val , int c) ;
long long query(int l , int r , int c);

int main(){
	int t ;
	scanf("%d" , &t) ;

	//freopen("out.txt" , "w" , stdout) ;
	while(t--){
		init() ;
		work() ;
	}
	
	return 0 ;
}

bool init(){
	
	if(scanf("%d %d %d" , &n , &m , &k)!=3){
		return 0 ;
	}
	
	memset(nsum , 0 , sizeof(nsum)) ;
	
	int i ;
	int j ;
	
	i = 1 ;
	
	while(i <= n){
		scanf("%d" , &nval[i]);
		i++ ;
	}
	
	for(i = 1 ; i <= k ; i ++)
		nsum[1] += nval[i] ;
		
	j = 2 ;
	
	for(i = k + 1 ; i <= n ; i ++){
		nsum[j] = nsum[j-1] + nval[i] - nval[i-k] ;
		j ++ ;	
	}	
	
	build(1 , n - k + 1 , 1) ;
	
	return 1 ;
}

void work(){
	
	int x ;
	int y ;
	int p ;
	int l ;
	int r ;
	
	while(m--){
		scanf("%d %d %d" , &p , &x , &y) ;
		
		if(p==0){
			solve(x , y - nval[x]) ;
			nval[x] = y ;
		}
		else if(p==1){
				solve(x , nval[y] - nval[x]) ;
				solve(y , nval[x] - nval[y]) ;
				
				int temp = nval[x] ;
				nval[x] = nval[y]  ;
				nval[y] = temp ;
		}
		else{
			l = x ;
			r = y - k + 1 ; 
			printf("%d\n", query(l , r , 1)) ;
		}
 	}
}

void solve(int x , int y){
	
	int l ;
	int r ;
	
	l = x - k + 1 ;	
	if(l < 1)
		l = 1 ;
	r = x ;
	if(x + k - 1 > n)
		r = n - k + 1 ;
		
	update(l , r , y , 1) ;

}

void build(int l , int r , int c){
	
	node[c].l = l ;
	node[c].r = r ;
	node[c].flag = 0 ;
	
	if(l == r){
		node[c].nmax = nsum[l] ;
		return ;
	}
	
	int mid = (l + r)/2 ;
	
	build(l , mid , c * 2) ;
	build(mid + 1 , r , c * 2 + 1) ;
	
	pushup(c) ;
}

void pushup(int root){
	
	node[root].nmax = max(node[root * 2].nmax , node[root * 2 + 1].nmax) ;
}

void pushdown(int root){
	
	if(node[root].flag==0)
		return ;
			
	node[root*2].flag += node[root].flag ;
	node[root*2+1].flag += node[root].flag ;
	
	node[root*2].nmax += node[root].flag ;
	node[root*2+1].nmax += node[root].flag ;
	
	node[root].flag = 0 ;
	
}

void update(int l , int r , int val , int c){
	pushdown(c) ;
	if(l == node[c].l  && node[c].r == r){
		node[c].flag += val ;
		node[c].nmax += val ;
		return ;
	}
	
	//pushdown(c) ;
	int mid = (node[c].l + node[c].r)/2 ;
	
	if(r <= mid){
		update(l , r , val , c*2) ;
	}
	else if(mid < l){
		update(l , r , val , c*2+1) ;
	}
	else{
		update(l , mid , val , c*2) ;
		update(mid + 1 , r , val , c*2+1) ;
	}
	
	pushup(c) ; 
}

long long query(int l , int r , int c){
	
	pushdown(c) ;	
	if(l == node[c].l && r == node[c].r){
		return node[c].nmax ;
	}
	int mid = (node[c].l  + node[c].r)/2 ;
	
	if(r <= mid){
		return query(l , r , c * 2) ;
	}
	
	if(l > mid){
		return query(l , r , c * 2 + 1) ;
	}

	return max(query(l , mid , c * 2 ) , query(mid + 1 , r , c * 2 + 1)) ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值