Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8647 Accepted Submission(s): 4195
这是一个区间染色的问题,对于区间染色问题,通常的方法是在线段树中定义一个cover域,当cover的值为-1的时候,则表示这个线段的覆盖不是有一个颜色染成的,其中包含了多种颜色,而当cover为一个非-1的值时,例如cover==1时表示该线段是有第一种颜色染成的。 对于这题,由于是成段成段的在跟新线段树,我们自然不能简单的递归到根节点再进行处理,这样毫无疑问是要超时的,所以我们只能成段的跟新。
那么,如何做到成段的跟新呢?这里需要运用一种叫着lazy的思想,lazy顾名思义便是懒惰的意思。该思想大概的意思便是:假设要跟新区间[a,b],那么当我们找到区间[a,b]时,便不再往下进行递归,而是在该区间上标记上一个lazy,表示这里有信息需要向下传递。那么当我们需要跟新区间[a,b/2]时,我们便一定会从区间[a,b]经过,经过的过程中,我们发现区间[a,b]有信息需要向下传递,此时便将区间[a,b]的信息传递给其子区间。这样在必要的时候才一层一层的传递,便节约了很多时间。具体见程序吧,很清晰的
#include <stdio.h>
#define maxn 900000
#define max(xx,yy) xx>yy?xx:yy
#define min(xx,yy) xx<yy?xx:yy
struct node
{
int l,r;
int cover;
}tree[maxn];
int ans;
void built( int s,int e,int n)
{
tree[n].l=s,tree[n].r=e,tree[n].cover=1;//初始颜色为1
if(s==e) return ;
int mid=(s+e)>>1;
built(s,mid,n*2);
built(mid+1,e,2*n+1);
}
void modify( int s,int e,int w,int n)//不懂?
{
if(tree[n].l>e||tree[n].r<s) return ;
if(tree[n].l>=s&&tree[n].r<=e)
{
tree[n].cover=w;
return ;
}
if(tree[n].cover!=-1)//该区间有信息需要传递
{
tree[2*n].cover=tree[2*n+1].cover=tree[n].cover;
tree[n].cover=-1;//同时自身取消标记
}
modify(s,e,w,2*n);
modify(s,e,w,2*n+1);
}
void solve( int i)
{
if(tree[i].cover!=-1)//单色区间,直接取其值
{
ans+=(tree[i].r-tree[i].l+1)*tree[i].cover;return ;
}
if(tree[i].l==tree[i].r) return;
solve(i*2);solve(i*2+1);//非单色区间,则向下递归
}
int main ( )
{
int N,M;
int test,i;
int x,y,v;
int t=0;
scanf("%d",&test);
while(test--)
{
scanf("%d",&N);
built(1,N,1);
scanf("%d",&M);
while(M--)
{
scanf("%d%d%d",&x,&y,&v);
modify(x,y,v,1);
}
ans=0;
solve(1);
printf("Case %d: The total value of the hook is %d.\n",++t,ans);
}
return 0;
}