两种做法。

第一种:标记区间最大值和最小值,若区间最小值>=P,则本区间+2c,若区间最大值<P,则本区间+c。非常简单的区间更新。

最后发一点牢骚:最后query查一遍就行,我这个2B竟然写了个for循环每个点查了一遍orz……然后比赛的时候就一直TLE还查不出原因……感觉线段树对我就像个诅咒一样,每场必不出,不管是多么简单的线段树,都会错在千奇百怪的地方……说到底也不过是对线段树掌握的不扎实罢了,sigh……以后要多加练习!

#include <cstdio>
#include <cstring>
#include <cstdlib> #define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define lc rt << 1
#define rc rt << 1 | 1 using namespace std; const int MAXN = ; int N, M, P;
int sum[MAXN << ];
int maxi[MAXN << ];
int mini[MAXN << ];
int lazy[MAXN << ]; void build( int l, int r, int rt )
{
sum[rt] = lazy[rt] = ;
maxi[rt] = ;
mini[rt] = ;
if ( l == r ) return;
int m = ( l + r ) >> ;
build( lson );
build( rson );
return;
} inline void PushDown( int rt, int m )
{
if ( lazy[rt] )
{
lazy[lc] += lazy[rt];
lazy[rc] += lazy[rt];
sum[lc] += lazy[rt]*(m - (m >> ) );
sum[rc] += lazy[rt]*(m >> );
maxi[lc] += lazy[rt], mini[lc] += lazy[rt];
maxi[rc] += lazy[rt], mini[rc] += lazy[rt];
lazy[rt] = ;
}
return;
} inline void PushUp( int rt )
{
sum[rt] = sum[lc] + sum[rc];
maxi[rt] = maxi[lc] > maxi[rc] ? maxi[lc] : maxi[rc];
mini[rt] = mini[lc] < mini[rc] ? mini[lc] : mini[rc];
return;
} inline void update( int L, int R, int val, int l, int r, int rt )
{
if ( L <= l && r <= R )
{
if ( maxi[rt] < P )
{
lazy[rt] += val;
sum[rt] += val*(r - l + );
maxi[rt] += val;
mini[rt] += val;
return;
}
else if ( mini[rt] >= P )
{
lazy[rt] += *val;
sum[rt] += *val*(r - l + );
maxi[rt] += *val;
mini[rt] += *val;
return;
}
}
if ( l == r ) return;
PushDown( rt, r - l + ); int m = ( l + r ) >> ;
if ( L <= m ) update( L, R, val, lson );
if ( R > m ) update( L, R, val, rson );
PushUp( rt ); return;
} bool first; void query( int l, int r, int rt )
{
if ( l == r )
{
if ( first ) putchar(' ');
first = true;
printf( "%d", sum[rt] );
return;
}
PushDown( rt, r - l + );
int m = ( l + r ) >> ;
query( lson );
query( rson );
return;
} int main()
{
while ( scanf( "%d%d%d", &N, &M, &P ) == )
{
build( , N, );
for ( int i = ; i < M; ++i )
{
int a, b, c;
scanf( "%d%d%d", &a, &b, &c );
update( a, b, c, , N, );
}
first = false;
query( , N, );
puts("");
}
return ;
}

第二种做法:线段树的特殊懒惰标记,方法跟 HDU 3954 一样。代码稍微改改就行。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm> #define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define lc rt << 1
#define rc rt << 1 | 1 using namespace std; const int MAXN = ;
const int INF = << ; struct node
{
int exp, level;
int min_dis;
int flag;
}; int N, M, P;
int K;
node Tr[ MAXN << ];
int sum[]; void build( int l, int r, int rt )
{
Tr[rt].exp = Tr[rt].flag = ;
Tr[rt].level = ;
Tr[rt].min_dis = sum[];
if ( l == r ) return ;
int m = ( l + r ) >> ;
build( lson );
build( rson );
return;
} void PushDown( int rt )
{
if ( Tr[rt].flag )
{
Tr[lc].exp += Tr[rt].flag * Tr[lc].level;
Tr[lc].min_dis -= Tr[rt].flag;
Tr[lc].flag += Tr[rt].flag; Tr[rc].exp += Tr[rt].flag * Tr[rc].level;
Tr[rc].min_dis -= Tr[rt].flag;
Tr[rc].flag += Tr[rt].flag; Tr[rt].flag = ;
}
return;
} void PushUp( int rt )
{
Tr[rt].level = max( Tr[lc].level, Tr[rc].level );
Tr[rt].exp = max( Tr[lc].exp, Tr[rc].exp );
Tr[rt].min_dis = min( Tr[lc].min_dis, Tr[rc].min_dis );
return;
} void Update( int L, int R, int v, int l, int r, int rt )
{
if ( l == r )
{
Tr[rt].exp += Tr[rt].level * v;
while ( Tr[rt].exp >= sum[ Tr[rt].level ] )
++Tr[rt].level;
Tr[rt].min_dis = ( sum[ Tr[rt].level ] - Tr[rt].exp ) / Tr[rt].level;
if( ( sum[ Tr[rt].level ] - Tr[rt].exp ) % Tr[rt].level ) ++Tr[rt].min_dis;
return;
}
int m = ( l + r ) >> ; if ( L == l && r == R )
{
if ( v >= Tr[rt].min_dis )
{
PushDown(rt);
if ( R <= m ) Update( L, R, v, lson );
else if ( L > m ) Update( L, R, v, rson );
else
{
Update( L, m, v, lson );
Update( m + , R, v, rson );
}
PushUp(rt);
}
else
{
Tr[rt].exp += Tr[rt].level * v;
Tr[rt].min_dis -= v;
Tr[rt].flag += v;
}
return;
} PushDown(rt); if ( R <= m ) Update( L, R, v, lson );
else if ( L > m ) Update( L, R, v, rson );
else
{
Update( L, m, v, lson );
Update( m + , R, v, rson );
} PushUp(rt); return;
} bool first; void Query( int l, int r, int rt )
{
if ( l == r )
{
if ( first ) putchar(' ');
first = true;
printf( "%d", Tr[rt].exp );
return;
}
PushDown(rt);
int m = ( l + r ) >> ;
Query( lson );
Query( rson );
return;
} int main()
{
K = ;
while ( scanf( "%d%d%d", &N, &M, &P ) == )
{
sum[] = P;
sum[] = INF; build( , N, );
while ( M-- )
{
int a, b, c;
scanf( "%d%d%d", &a, &b, &c );
Update( a, b, c, , N, );
}
first = false;
Query( , N, );
puts("");
}
return ;
}

HDU 4107 Gangster(线段树 特殊懒惰标记)的更多相关文章

  1. HDU 3397 线段树 双懒惰标记

    这个是去年遗留历史问题,之前思路混乱,搞了好多发都是WA,就没做了 自从上次做了大白书上那个双重懒惰标记的题目,做这个就思路很清晰了 跟上次大白上那个差不多,这个也是有一个sets标记,代表这个区间全 ...

  2. hdu 1828 Picture(线段树 || 普通hash标记)

    http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others)    Mem ...

  3. poj3468 线段树的懒惰标记

    题目链接:poj3468 题意:给定一段数组,有两种操作,一种是给某段区间加c,另一种是查询一段区间的和 思路:暴力的方法是每次都给这段区间的点加c,查询也遍历一遍区间,复杂度是n*n,肯定过不去,另 ...

  4. HDU 3954 Level up (线段树特殊懒惰标记)

    http://blog.csdn.net/acm_cxlove/article/details/7548087 感觉最巧的是定义了min_dis……将区间内有无英雄升级分开处理 #include &l ...

  5. hdu 4031 attack 线段树区间更新

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Subm ...

  6. hdu 4288 离线线段树+间隔求和

    Coder Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  7. hdu 3016 dp+线段树

    Man Down Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  8. Transformation HDU - 4578(线段树——懒惰标记的妙用)

    Yuanfang is puzzled with the question below: There are n integers, a 1, a 2, …, a n. The initial val ...

  9. hdu 4107 Gangster(线段树,时间卡得很严)

    这道题目的数据卡得好厉害. 题目明显是考察线段树延迟标记的,但是因为要考虑到p的值,这种延迟是有条件的:在该节点下所有的数据对于p都应该位于p的同一侧.要么都比p大,要么都比p小. 开始的时候我用一个 ...

随机推荐

  1. weight decay 和正则化caffe

    正则化是为了防止过拟合,因为正则化能降低权重 caffe默认L2正则化 代码讲解的地址:http://alanse7en.github.io/caffedai-ma-jie-xi-4/ 重要的一个回答 ...

  2. Java 执行系统命令工具类(commons-exec)

    依赖jar <!-- 可以在JVM中可靠地执行外部进程的库. --> <dependency> <groupId>org.apache.commons</gr ...

  3. 【转】git 删除本地分支和远程分支、本地代码回滚和远程代码库回滚

    转载自:http://m.blog.csdn.net/blog/lihongli528628/45483463 [git 删除本地分支] git branch -D br [git 删除远程分支] g ...

  4. kubernetes-控制器statefulset和Job(十三)

       从前面的学习我们知道使用Deployment创建的pod是无状态的,当挂载了Volume之后,如果该pod挂了,Replication Controller会再启动一个pod来保证可用性,但是由 ...

  5. Notepad++配色方案

    1.下载notepad++样式文件 styles.xml 2.将该文件拷贝到 C:\Users\Administrator\AppData\Roaming\Notepad++ 目录(将Administ ...

  6. 前端小记4——高性能mobile web开发

    1.高性能CSS3动画 与PC端场景需要相比,移动web端需要考虑的因素也相对复杂,重点考虑:流量.功耗与流畅度.在pc端上考虑更多的是流畅度,而mobile web中需要考虑网络流量的使用和耗电情况 ...

  7. IE 兼容模式 设置 Meta Compatible 和 Iframe 子页面的关系

    背景 因为历史原因,之前很多的系统都会是 顶级页面+Iframe来加载子级页面的这种模式构件系统,而且系统都只能运行在IE6或者IE 高版本兼容模式下(IE 7模式). 随着现在的审美原来越高,脚本能 ...

  8. 基于Vue的SPA如何优化页面加载速度

    常见的几种SPA优化方式 减小入口文件体积 静态资源本地缓存 开启GZip压缩 使用SSR ..... 减小入口文件体积,常用的手段是路由懒加载,开启路由懒加载之后,待请求的页面会单独打包js文件,使 ...

  9. 【杂题总汇】HDU多校赛第十场 Videos

    [HDU2018多校赛第十场]Videos 最后一场比赛也结束了…… +HDU传送门+ ◇ 题目 <简要翻译> 有n个人以及m部电影,每个人都有一个快乐值.每场电影都有它的开始.结束时间和 ...

  10. Servlet学习笔记04——什么是重定向,servlet生命周期?

    1.重定向 (1)什么是重定向? 服务器通知浏览器访问一个新的地址. 注: 服务器可以通过发送一个302状态码及一个 Location消息头(该消息头的值是一个地址,一般 称之为重定向地址)给浏览器, ...