HDU1698 Just a Hook(線段樹區間更新、區間查詢)
阿新 • • 發佈:2019-01-26
題目連結
題意
在 DotA 遊戲中,帕吉的肉鉤是很多英雄最害怕的東西。鉤子由連續若干段的等長金屬棒製成。
現在帕吉對鉤子由一些操作:
我們將金屬棒 1~n 依次編號,帕吉可以把編號 x~y 的金屬棒變成銅棒、銀棒、金棒。
每段銅棒的價值是 1;每段銀棒的價值是 2;每段金棒的價值是 3。
肉鉤的總價值是 n 段金屬棒價值之和。
帕吉想知道若干操作以後鉤子的總價值。
題解
線段樹區間更新、區間查詢問題。
區間更新原理:每一個節點代表一個區間上的資訊,對區間進行修改,即對若干個對應的節點進行修改。而考慮到暴力修改所有節點的時間複雜度難以接受,所以引入一個延遲標記。
也就是說只修改一個節點,而對該節點的子節點暫時不修改,等到下一次需要用到該節點的子節點時(包括更新和修改),再根據延遲標記進行修改。
程式碼
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=4e5+100;
int s[maxn],color[maxn];
void down(int p,int l,int r)
{
if(color[p])
{
int mid=(l+r)/2;
s[p*2]=(mid-l+1)*color[p];
s[p*2+1]=(r-mid)*color[p];
color[p*2]=color[p*2 +1]=color[p];
color[p]=0;
}
}
void up(int p)
{
s[p]=s[p*2]+s[p*2+1];
}
int query(int p,int l,int r,int x,int y)
{
if(x<=l && r<=y)
{
return s[p];
}
down(p,l,r);
int mid=(l+r)/2,ret=0;
if(x<=mid) ret+=query(p*2,l,mid,x,y);
if(y>mid) ret+=query(p*2 +1,mid+1,r,x,y);
up(p);
return ret;
}
void modify(int p,int l,int r,int x,int y,int z)
{
if(x<=l && r<=y)
{
s[p]=(r-l+1)*z;
color[p]=z;
return;
}
down(p,l,r);
int mid=(l+r)/2;
if(x<=mid) modify(p*2,l,mid,x,y,z);
if(y>mid) modify(p*2+1,mid+1,r,x,y,z);
up(p);
}
int main()
{
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
memset(s,0,sizeof(s));
memset(color,0,sizeof(color));
int N;
scanf("%d",&N);
modify(1,1,N,1,N,1);
int Q;
scanf("%d",&Q);
while(Q--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
modify(1,1,N,x,y,z);
}
printf("Case %d: The total value of the hook is %d.\n",i,query(1,1,N,1,N));
}
return 0;
}