hdu1698 Just a Hook

        题意:看到题意和配图,我也是醉了。。。DotA屠夫的钩,是一节一节组成的,有n节,初始每节的长度是1。屠夫可以改变一个区间内每节的长度为1,2,3。。。问q次改变以后,总长度是多少。

        思路:线段树(区间更新)。区间保存的是对应钩子区间每节的长度,如果区间内长度不一,则这个区间是无效的,需要考察这个区间的子区间,直到有一个统一的长度。


#include <iostream>    
#include <stdio.h>    
#include <cmath>    
#include <algorithm>    
#include <iomanip>    
#include <cstdlib>    
#include <string>     
#include <vector>    
#include <queue>    
#include <stack>    
#include <map>  
#include <set>  
#include <ctype.h>    

using namespace std;  

struct node{
	int l;
	int r;
	int val;
	bool flag;
};

node tree[400010];

void build_tree(int n,int l,int r){
	tree[n].l=l; tree[n].r=r; tree[n].val=1; tree[n].flag=1;
	if(l==r)return;
	int mid=(l+r)/2;
	build_tree(n*2,l,mid);
	build_tree(n*2+1,mid+1,r);
}

void update(int n,int l,int r,int v){
	if(tree[n].l==l&&tree[n].r==r){
		tree[n].val=v; tree[n].flag=1;
		return;//应用了lazy思想,暂时不更新子区间。 
	}
	
	int mid=(tree[n].l+tree[n].r)/2;
	if(tree[n].flag){//这个时候不得不更新子区间了。 
		update(n*2,tree[n].l,mid,tree[n].val);
		update(n*2+1,mid+1,tree[n].r,tree[n].val);
	}
	if(r<=mid){
		update(n*2,l,r,v);
	}else{
		if(l<=mid){//跨区间 
			update(n*2,l,mid,v);
			update(n*2+1,mid+1,r,v);
		}else{
			update(n*2+1,l,r,v);
		}
	}
	tree[n].flag=0;
}

int sum(int n){
	if(tree[n].flag||(tree[n].l==tree[n].r)){
		int tmp=tree[n].val;
		return (tree[n].r-tree[n].l+1)*tree[n].val;
	}
	return sum(n*2)+sum(n*2+1);
}

int main(){
	int t;
	cin>>t;
	int cas=0;
	while(t--){
		cas++;
		int n,q;
		cin>>n>>q;
		build_tree(1,1,n);
		while(q--){
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			update(1,a,b,c);
		}
		printf("Case %d: The total value of the hook is %d.\n",cas,sum(1));
	}
	return 0;
}


你可能感兴趣的:(线段树)