HDU 4107 Gangster (线段树)
2011-11-12 22:51
225 查看
这道题,一看题大概就知道是线段树。
对于这种题通常来说就是看节点中如何记录信息了……
这道题我们使用:
v记录区间的改变值,也就是在update过程中累加的改变值
Max表示整个区间的最大值
Min表示整个区间的最小值
当然还有l和r不用说了。
当一个区间的Max<p的时候我们就对这个区间的v值加上c,当一个区间的的Min>=p的时候,我们就将这个区间的v值加上2*c;等到所有的update完成之后,直接查询每个点的v值就是最终输出的答案了……
如果不会写可以看下代码:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int Max= 200010;
typedef struct SEGMENT
{
int l,r;
int v,Max,Min;
}Segment;
Segment seg[Max*4];
int n,m,p;
int inline max(int a,int b)
{
if(a<b) return b;
else return a;
}
int inline min(int a,int b)
{
if(a<b) return a;
else return b;
}
void init(int l,int r,int k)
{
seg[k].l=l,seg[k].r=r;
seg[k].v=seg[k].Max=seg[k].Min=0;
if(l==r)
return ;
init(l,(l+r)>>1,k<<1);
init(((l+r)>>1)+1,r,(k<<1)+1);
}
void inline pushDown(int k)
{
int v=seg[k].v;
if(seg[k].v>0)
{
seg[k<<1].v+=seg[k].v,seg[k<<1].Min+=v,seg[k<<1].Max+=v;
seg[(k<<1)+1].v+=seg[k].v,seg[(k<<1)+1].Min+=v,seg[(k<<1)+1].Max+=v;
seg[k].v=0;
}
}
void inline pushUp(int k)
{
seg[k].Max=max(seg[k<<1].Max,seg[(k<<1)+1].Max);
seg[k].Min=min(seg[k<<1].Min,seg[(k<<1)+1].Min);
}
void update(int l,int r,int c,int k)
{
if(seg[k].l==l&&seg[k].r==r&&(seg[k].Max<p||seg[k].Min>=p))
{
if(seg[k].Max<p)
{
seg[k].v+=c;
seg[k].Max+=c;
seg[k].Min+=c;
}
else if(seg[k].Min>=p)
{
seg[k].v+=(c<<1);
seg[k].Max+=(c<<1);
seg[k].Min+=(c<<1);
}
return ;
}
if(seg[k].v)
pushDown(k);
int mid=(seg[k].l+seg[k].r)>>1;
if(r<=mid)
update(l,r,c,k<<1);
else if(l>mid)
update(l,r,c,(k<<1)+1);
else
{
update(l,mid,c,2*k);
update(mid+1,r,c,2*k+1);
}
pushUp(k);
}
int read(int id,int k)
{
if(seg[k].l==id&&seg[k].r==id)
{
return seg[k].v;
}
if(seg[k].v>0)
pushDown(k);
int mid=(seg[k].l+seg[k].r)>>1;
if(id<=mid)
return read(id,k<<1);
else if(id>mid)
return read(id,(k<<1)+1);
}
int main()
{
int a,b,c;
while(scanf("%d%d%d",&n,&m,&p)!=EOF)
{
init(1,n,1);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1);
}
for(int i=1;i<=n;i++)
{
printf("%d%c",read(i,1),i==n?'\n':' ');
}
}
return 0;
}
对于这种题通常来说就是看节点中如何记录信息了……
这道题我们使用:
v记录区间的改变值,也就是在update过程中累加的改变值
Max表示整个区间的最大值
Min表示整个区间的最小值
当然还有l和r不用说了。
当一个区间的Max<p的时候我们就对这个区间的v值加上c,当一个区间的的Min>=p的时候,我们就将这个区间的v值加上2*c;等到所有的update完成之后,直接查询每个点的v值就是最终输出的答案了……
如果不会写可以看下代码:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int Max= 200010;
typedef struct SEGMENT
{
int l,r;
int v,Max,Min;
}Segment;
Segment seg[Max*4];
int n,m,p;
int inline max(int a,int b)
{
if(a<b) return b;
else return a;
}
int inline min(int a,int b)
{
if(a<b) return a;
else return b;
}
void init(int l,int r,int k)
{
seg[k].l=l,seg[k].r=r;
seg[k].v=seg[k].Max=seg[k].Min=0;
if(l==r)
return ;
init(l,(l+r)>>1,k<<1);
init(((l+r)>>1)+1,r,(k<<1)+1);
}
void inline pushDown(int k)
{
int v=seg[k].v;
if(seg[k].v>0)
{
seg[k<<1].v+=seg[k].v,seg[k<<1].Min+=v,seg[k<<1].Max+=v;
seg[(k<<1)+1].v+=seg[k].v,seg[(k<<1)+1].Min+=v,seg[(k<<1)+1].Max+=v;
seg[k].v=0;
}
}
void inline pushUp(int k)
{
seg[k].Max=max(seg[k<<1].Max,seg[(k<<1)+1].Max);
seg[k].Min=min(seg[k<<1].Min,seg[(k<<1)+1].Min);
}
void update(int l,int r,int c,int k)
{
if(seg[k].l==l&&seg[k].r==r&&(seg[k].Max<p||seg[k].Min>=p))
{
if(seg[k].Max<p)
{
seg[k].v+=c;
seg[k].Max+=c;
seg[k].Min+=c;
}
else if(seg[k].Min>=p)
{
seg[k].v+=(c<<1);
seg[k].Max+=(c<<1);
seg[k].Min+=(c<<1);
}
return ;
}
if(seg[k].v)
pushDown(k);
int mid=(seg[k].l+seg[k].r)>>1;
if(r<=mid)
update(l,r,c,k<<1);
else if(l>mid)
update(l,r,c,(k<<1)+1);
else
{
update(l,mid,c,2*k);
update(mid+1,r,c,2*k+1);
}
pushUp(k);
}
int read(int id,int k)
{
if(seg[k].l==id&&seg[k].r==id)
{
return seg[k].v;
}
if(seg[k].v>0)
pushDown(k);
int mid=(seg[k].l+seg[k].r)>>1;
if(id<=mid)
return read(id,k<<1);
else if(id>mid)
return read(id,(k<<1)+1);
}
int main()
{
int a,b,c;
while(scanf("%d%d%d",&n,&m,&p)!=EOF)
{
init(1,n,1);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1);
}
for(int i=1;i<=n;i++)
{
printf("%d%c",read(i,1),i==n?'\n':' ');
}
}
return 0;
}
相关文章推荐
- hdu 4107 Gangster(线段树)
- hdu_4107Gangster_线段树_区间修改
- hdu 4107 Gangster 线段树 成段更新 最后求每一位的值
- hdu 4107 Gangster(线段树,时间卡得很严)
- hdu 4107 Gangster 线段树
- HDU 4107 Gangster(线段树 特殊懒惰标记)
- hdu 4107 Gangster(线段树,时间卡得很严)
- hdu 4107 Gangster 线段树 成段更新
- hdu 4107 Gangster(区间更新)
- hdu 4107 Gangster 线段数
- hdu 4107 Gangster (离线+打标记+树状数组)
- HDU 4107 Gangster
- HDU 4107 线段树
- HDU 4107 Gangster Segment Tree线段树
- HDU 4107 线段树
- 线段树_HDU_4107
- HDU 4107(线段树 特殊懒惰标记)g++ TLE,c++才过(呜呜呜呜)
- hdu 4107 Gangster
- HDOJ 题目4107 Gangster(线段树)
- HDU 4107 Gangster Segment Tree线段树