SDUT 2880 The 5th Shandong ACM Provincial Competition Devour Magic (Line Segment Tree + Interval Processing) 57 lines of code to get it~

Portal: SDUT 2880



Topic meaning:

There are n ( 1<= n <= 1e5) points on the number line from 1 to n, each point will add 1 unit of mana per unit of time, given a person's m operations in chronological order, each operation will be in At time t, take away all the mana in the interval [ l , r ], and ask him what the sum of the mana taken away is.



Ideas:

For each point, the sum of the mana taken from that point is equal to the time it was last taken from it (think about it yourself).


Since m operations are given in chronological order, we can "color" the points in the interval in chronological order, and the value of each coloring is the time t of the operation. This way, each point holds the color corresponding to the time of the last operation.


All we need to do to calculate the result is to add the value of each point in O(n) time. This time is not much. The time-consuming operation is to color the interval. We can use the line segment tree to solve it, which is somewhat similar to the operation of the line segment tree to find the interval sum.



Implementation:

We can use the col property of the points of the segment tree to record the "color" of each point, ie the time of the last operation. Since the interval is colored each time, the col is delayed each time (to save time). Since the color of each point is not directly recorded, it is necessary to use the query function to recursively query the color of each point, and add the color values ​​of the points to obtain the result.



Note:

1. I see that many methods on the Internet are based on the idea of ​​simulation, and the interval must be cleared every time after taking it, which is a little more troublesome.


2. This question is very similar to poj 2528. Poj 2528 means to put a poster on a board, give the interval of the poster, and ask how many posters are visible at the end (some of them can be seen).



Code:

#include<stdio.h>
#include<string.h>
typedef long long LL;

//Note that the a array is 4 times larger, and the col array is 16 times larger
int a[100010*4],col[100010*16];

void pushdown(int root)
{ //延迟标记 
	//让左右子树的根节点染色为当前根节点的染色 
	col[root<<1]=col[root<<1|1]=col[root];	
	col[root]=0; //当前节点设为未染色 
}

void update(int root,int L,int R,int l,int r,int x)
{ //更新函数,参数为:根,大区间,所查询区间, 染第x种色 
	if(l<=L&&r>=R)
	{ //如果当前区间在查询区间内,则染色 
		col[root]=x;
		return;
	}
	if(col[root]!=0) pushdown(root);
	int mid=(L+R)>>1;
	if(mid>=l) update(root<<1,L,mid,l,r,x); //更新左子树 
	if(mid<r) update(root<<1|1,mid+1,R,l,r,x); //更新右子树 
}

LL query(int root,int L,int R,int l,int r)
{ //查询函数,参数为:根,大区间,所查询区间
	LL ans=0;
	if(L==R) return col[root];
	if(col[root]!=0) pushdown(root); //延迟标记 
	int mid=(L+R)>>1;
	if(mid>=l) ans+=query(root<<1,L,mid,l,r); //查询左子树 
	if(mid<r) ans+=query(root<<1|1,mid+1,R,l,r); //查询右子树 
	return ans;
}

int main()
{
	int i,t,n,m,l,r,color;
	scanf("%d",&t);
	while(t--)
	{
		memset(col,0,sizeof(col)); //初始化,相当于建树 
		scanf("%d%d",&n,&m);		
		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&color,&l,&r);
			update(1,1,n,l,r,color); //更新区间的颜色 
		}		
		//用query函数递归查询每个点的颜色并相加 
		LL ans=query(1,1,n,1,n);
		printf("%lld\n",ans);
	}
	return 0;
}


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324840444&siteId=291194637