[CodeChef] The Street
给定两个长度为n的数列A和B,开始数组A中每一项值为0,数组B中每一项值为负无穷大。接下来有m次操作:1.数组A区间加一个等差数列;2.数组B区间对一个等差数列取max;3.询问ai+bi的值。n<=1e9,m<=3e5。
这道题做了两天。。告诉我:要随着递归函数变的变量,千万不要放在全局。。
#include <cstdio>
using namespace std; //#bug2:LL
typedef long long LL;
const LL maxn=1e9+, maxm=3e5+;
const LL INF=1ll<<;
//#bug10:INF不够大
LL n, m, op, l2s, cnt;
LL u, v, a, b, x; //注意a,b是一直不变的
LL ll, rr;
//注意值最多可以加到LL外!
struct node{
LL b1, change1; //max
LL a1;
LL a2, b2; //add
LL lc, rc;
}seg[maxm**]; inline LL abs(LL x) { return x>?x:-x; }
inline LL max(LL x, LL y) { return x>y?x:y; } void flag(LL now, LL a1, LL b1, LL a2, LL b2);
//给孩子打上标记
void push_down(LL &now, LL l, LL r, LL a, LL b){
//#bug4:忘记新建结点
if (!now) now=++cnt, seg[now].a1=-INF;
//#bug5:历史遗留问题(话说这个pushdown有点多余)
//#bug7:b值有变化。。现在更新的b值不与下传的b值相同
//更新的是目前uvab,下传的是这个结点的ab。(在下面修正)
flag(now, seg[now].a1, seg[now].a1+(r-l)*seg[now].b1,
a, a+(r-l)*b);
}
//取max,当然是标记永久化!
void flag(LL now, LL a1, LL b1, LL a2, LL b2){
//有个新来的数列的公差b,是在外面的
//如果a1,b1没有值,或者盖住,那就直接赋值
//bug#6:a1没有值的时候应该是负无穷大
if (seg[now].a1==-INF||(a1<=a2&&b1<=b2)){
seg[now].a1=a2, seg[now].b1=b;
seg[now].change1=;
return;
}
if (a1>a2&&b1>b2) return;
//那么现在必定有区间内交点
LL mid=(ll+rr)>>;
LL nowl, nowr;
if (abs(a1-a2)<abs(b1-b2)){ //交点在左边
//如果a1右半部分更小,就全部赋值(#bug7:注意下传标记!)
if (a1>a2) {
LL tmp=b; b=seg[now].b1;
//它的孩子替换成自己
//bug#9:l和r不对
nowl=ll, nowr=rr; rr=mid;
push_down(seg[now].lc, ll, mid, seg[now].a1, seg[now].b1);
rr=nowr; ll=mid+;
push_down(seg[now].rc, mid+, rr,
seg[now].a1+(mid+-nowl)*seg[now].b1, seg[now].b1);
ll=nowl;
b=tmp;
seg[now].a1=a2, seg[now].b1=b, seg[now].change1=;
}
//反之,把新数列的左半边往下传(它的孩子替换成新的)
//#bug7:忽略了等于的情况(证伪)
if (a1<=a2) { //#bug8:b不对。就是原来的
nowr=rr; rr=mid;
push_down(seg[now].lc, ll, mid, a2, b);
rr=nowr;
}
} else {
//与之前相同(它的孩子替换成新的)
if (a1>=a2) { //同bug8
//#bug9:下面的式子还是要用原来的ll
nowl=ll; ll=mid+;
push_down(seg[now].rc, mid+, rr, a2+(mid+-nowl)*b, b);
ll=nowl;
}
//同bug7(证伪)
if (a1<a2) {
LL tmp=b; b=seg[now].b1;
//它的孩子替换成自己(注意下传标记!)
nowl=ll, nowr=rr; rr=mid;
push_down(seg[now].lc, ll, mid, seg[now].a1, seg[now].b1);
rr=nowr; ll=mid+;
push_down(seg[now].rc, mid+, rr,
seg[now].a1+(mid+-nowl)*seg[now].b1, seg[now].b1);
ll=nowl;
b=tmp;
seg[now].a1=a2, seg[now].b1=b, seg[now].change1=;
}
}
}
void modify1(LL &now, LL l, LL r){
if (!now) now=++cnt, seg[now].a1=-INF; //用引用新建结点,这样空的不会被识别
l2s=a+(l-u)*b; //l这个x坐标上的l2的值
ll=l, rr=r;
LL mid=(l+r)>>;
LL nowl, nowr;
//如果修改过,必须再这里先push一下,不然flag的时候,可能会覆盖
if (seg[now].change1){
LL tmp=b; b=seg[now].b1;
//它的孩子替换成自己
nowl=ll, nowr=rr; rr=mid;
push_down(seg[now].lc, l, mid, seg[now].a1, seg[now].b1);
rr=nowr, ll=mid+;
push_down(seg[now].rc, mid+, r,
seg[now].a1+(mid+-nowl)*seg[now].b1, seg[now].b1);
ll=nowl;
b=tmp;
//#bug3:mid+1全没加 (还是mid!!)
seg[now].change1=;
}
if (l>=u&&r<=v){
//给出俩直线开始结束,修改下传结点。只要判断交点位置
flag(now, seg[now].a1, seg[now].a1+(r-l)*seg[now].b1,
l2s, l2s+(r-l)*b);
return;
}
if (mid>=u) modify1(seg[now].lc, l, mid);
if (mid<v) modify1(seg[now].rc, mid+, r);
}
//这个。。可以差分
void modify2(LL &now, LL l, LL r){
if (!now) now=++cnt, seg[now].a1=-INF; //这样空的不会被识别
l2s=a+(l-u)*b;
if (l>=u&&r<=v){
seg[now].a2+=l2s, seg[now].b2+=b;
return;
}
LL mid=(l+r)>>;
if (mid>=u) modify2(seg[now].lc, l, mid);
if (mid<v) modify2(seg[now].rc, mid+, r);
}
LL q1(LL now, LL l, LL r){ //只有当路径上全部都是-INF时,这个东西不存在
if (!now) return -INF;
LL mid=(l+r)>>, v=seg[now].a1+(x-l)*seg[now].b1;
if (mid>=x) return max(v, q1(seg[now].lc, l, mid));
else return max(v, q1(seg[now].rc, mid+, r));
}
LL q2(LL now, LL l, LL r){ //差分。。
if (!now) return ;
LL mid=(l+r)>>, v=seg[now].a2+(x-l)*seg[now].b2;
if (mid>=x) return v+q2(seg[now].lc, l, mid); //bug#1,mid>x
else return v+q2(seg[now].rc, mid+, r);
} int main(){
scanf("%lld%lld", &n, &m);
LL root=++cnt; seg[root].a1=-INF;
for (LL i=; i<m; ++i){
scanf("%lld", &op);
//这里把a看成开始,b看成公差!
if (op<) {
scanf("%lld%lld%lld%lld", &u, &v, &a, &b);
LL t=a; a=b; b=t;
}
if (op==) modify1(root, , n);
if (op==) modify2(root, , n);
if (op==){
scanf("%lld", &x);
LL query1=q1(, , n), query2=q2(, , n);
if (query1==-INF) { printf("NA\n"); continue; }
printf("%lld\n", query1+query2);
}
}
return ;
}
[CodeChef] The Street的更多相关文章
- Codechef March Challenge 2014——The Street
The Street Problem Code: STREETTA https://www.codechef.com/problems/STREETTA Submit Tweet All submis ...
- AC日记——The Street codechef March challenge 2014
The Street 思路: 动态开节点线段树: 等差序列求和于取大,是两个独立的子问题: 所以,建两颗线段树分开维护: 求和:等差数列的首项和公差直接相加即可: 取大: 对于线段树每个节点储存一条斜 ...
- [CodeChef - STREETTA] The Street 李超线段树
大致题意: 给出两个序列A,B,A初始为负无穷,B初始为0,有三种操作 1.在A上区间[u,v]上加一个等差数列,取与原本A序列的最大值. 2.在B上区间[u,v]上加一个等差数列. 3.给出一个点X ...
- 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树
3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1288 Solved: 490 ...
- 申请邓白氏编码的时候总是提示 Enter a valid Street Address 怎么办?
今天要申请一个苹果开发者公司(Company)账号,然后需要邓白氏编码,然后填写企业的基本信息.其中对于Street Address认真的对照着中文翻译为如下格式: Kang Hesheng buil ...
- ACM: 限时训练题解-Street Lamps-贪心-字符串【超水】
Street Lamps Bahosain is walking in a street of N blocks. Each block is either empty or has one la ...
- Codeforce - Street Lamps
Bahosain is walking in a street of N blocks. Each block is either empty or has one lamp. If there is ...
- 【BZOJ4260】 Codechef REBXOR 可持久化Trie
看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...
- Wall Street English
1月23号,报名Wall Street English!
随机推荐
- invalid constant type: 18
javassist 3.18以下的版本不支持在JDK1.8下运行
- python 正则表达式(一)
正则表达式(简称RE)本质上可以看作一个小的.高度专业化的编程语言,在Python中可以通过re模块使用它.使用正则表达式,你需要为想要匹配的字符串集合指定一套规则,字符串集合可以包含英文句子.e-m ...
- jQuery向上遍历DOM树之parents(),parent(),closest()之间的区别
http://www.poluoluo.com/jzxy/201312/253059.html 在这个sprint中,因为要写前端UI,所以用到了jQuery,但是jQuery在向上遍历DOM树的AP ...
- JavaUtil_09_通用工具类-01_Hutool
一.重要的官方资料 1. Hutool 官网 2. Hutool 参考文档 3. Hutool API文档
- 移动端H5 button 默认事件
button 在移动端下会有自带的默认事件,如果不处理的话,点击按钮的时候会有自动刷新页面的效果,原因就是button的默认事件没有阻止. 所以在点击事件里面要加上 e.preventDefault( ...
- 多版本Python共存时pip给指定版本的python安装package的方法
在Linux安装了多版本Python时(例如python2.7和3.6),pip安装的包不一定是用户想要的位置,此时可以用 -t 选项来指定位置. 例如目标位置是/usr/local/lib/pyth ...
- 多puppetmaster,多ca,keepalived+haproxy(nginx)puppet集群搭建
多puppetmaster,多ca,keepalived+haproxy(nginx)puppet集群搭建 一.服务器详情 192.168.122.111 pm01.jq.com pm01 #(pup ...
- RS-485半双工延时问题
学习485总线时,遇到延时问题,困扰很久.通过学习知道了485半双工收发时必须延时,以保证系统的稳定性.可靠性.好多资料都介绍了485 防静电.抗干扰电路.惟独没提 每一帧收发停止位(或第9位)的延时 ...
- 1.Apache+Tomcat负载均衡+集群配置
1.本文Apache+Tomcat集群配置 基于最新的Apache和Tomcat,具体是2011年4月20日最新的Tomcat和Apache集群和负载均衡配置. 准备环境 Apache Apache是 ...
- JS取得绝对路径
在项目中,我们经常要得到项目的绝对路径,方便我们上传下载文件,JS为我们提供了方法,虽说要迂回一下.代码如下: function getRealPath(){ //获取当前网址,如: h ...