GSS2-Can you answer these queries II
---恢复内容开始---
这道题真的是非常恶心,看题解看了半天才弄懂,而且题解上说的相当简略。
此题大意是询问去掉重复元素的最大子区间和,没有修改操作。
没有修改操作,这样就可以离线处理了。
这道题有几个难点:
1.怎么表示去掉重复元素的区间和?
有一种简便而且高效的方法,用pos[a[i]]表示a[i]上次出现的位置,用s[j]表示从j到i(当前处理的元素)的去掉重复元素的区间和.每次加入一个数a[i],将s[pos[a[i]]+1]到s[i]全部加上a[i](这里要用到线段树的区间更新),就表示出了去掉重复元素的区间和,顺着这个思路想下去,当我们把a[i]加进来的时候,如果i恰好是询问的区间的有端点,那么s[L]到s[R]所有出现过的值中的最大值就是我们要求的答案.
2.为什么要对区间进行排序?
假设一个询问是(1,3) 当我们把a[4]加进来的时候,我们会改变s[pos[a[4]]+1]到s[4]所有的值,如果pos[a[4]]+1<=3,那么s[pos[a[4]]+1]就被a[4]影响了,讲导致我们难以得出正确答案.将区间按照右端点排序过后,处理了其右端点,就记录下查询的结果,这样在处理后面的点时就不用担心影响了前面的区间.
3.怎么求出历史最大值?
我们需要维护四个值
max_now:去掉重复元素的区间和 max_old:历史最大值
tag_now:区间上的更新 tag_old:区间上的最大更新(是针对整个区间的更新,不是点)
tag_now和tag_old实际上就是max_now和max_old的标签,tag_now很好理解,操作起来和普通的区间更新一样。tag_old比较迷,要弄清楚一点,我们维护tag_old的目的是为了得出max_old的值。
我们来详细看下51行这句代码:
tag_old[rt]=max(tag_old[rt],tag_now[rt]+=add);
这其实有两个命令,tag_now[rt]+=add; tag_old[rt]=max(tag_old[rt],tag_now[rt]);第一个命令很好理解,就是普通的标签。第二句就体现了tag_old的意义:记录最大的更新值,注意:每次更新都是针对一个连续的区间的。
这里的代码为什么不是tag_old[rt]=max(tag_old[rt],tag_old[rt]+add);呢?因为这样做有可能把区间割裂开,比如说有4个数是2 -1 -3 1执行这个命令就相当于把2加进去的时候tag_old[1]=2,然后加-1和-3的时候tag_old[1]不会更新,把1加进去的时候又会更新tag_old[1]=2+1=3,此时,就相当于把2和1加起来了而没有加上-1和-3,不再是一个连续的区间!
在向下传递tag的时候也是同样的道理tag_old和max_old要么不变,要么就可以由当前的区间来更新,注意不是点。向下传递tag的代码也可以用类型的思路来理解,要时刻保持区间的连续性。
最后注意一点,就是传递tag时的顺序,必须先更新tag_old和max_old,因为更新这两个的时候要用到tag_now和max_now,如果先改变了tag_now和max_now,就相当于已经把区间上所有的元素加起来了,显然不是“最大自区间”。
代码如下:
#include<bits/stdc++.h>
#define rep(i,n) for(i=1;i<=n;i++)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define creatmid int mid=(l+r)>>1
using namespace std;
typedef long long int ll;
const int N=1e5+5;
ll max_now[N*4],max_old[N*4],tag_now[N*4],tag_old[N*4],a[N],ans[N];
int n,q,pos[N*2+5];
struct zz
{
int L,R,id;
bool operator<(const zz&u)const
{
return R<u.R;
}
}Q[N];
void PushUp(int rt)
{
//if(rt==13)printf("%d\n",tag_old[rt]);
max_now[rt]=max(max_now[rt<<1],max_now[rt<<1|1]);
max_old[rt]=max(max_old[rt<<1],max_old[rt<<1|1]);
}
void PushDown(int l,int r,int rt)
{
if(l==r)
{
tag_old[rt]=0;
tag_now[rt]=0;
return ;
}
tag_old[rt<<1]=max(tag_old[rt<<1],tag_now[rt<<1]+tag_old[rt]);
tag_old[rt<<1|1]=max(tag_old[rt<<1|1],tag_now[rt<<1|1]+tag_old[rt]); max_old[rt<<1]=max(max_old[rt<<1],max_now[rt<<1]+tag_old[rt]);
max_old[rt<<1|1]=max(max_old[rt<<1|1],max_now[rt<<1|1]+tag_old[rt]); max_now[rt<<1]+=tag_now[rt];max_now[rt<<1|1]+=tag_now[rt];
tag_now[rt<<1]+=tag_now[rt];tag_now[rt<<1|1]+=tag_now[rt]; tag_old[rt]=tag_now[rt]=0;
//if(rt==13)printf("%d\n",tag_old[rt]);
}
void update(int L,int R,ll add,int l,int r,int rt)
{
//if(rt==13)
// printf("L=%d R=%d add=%lld l=%d r=%d rt=%d\n",L,R,add,l,r,rt);
if(l>=L && r<=R)
{
tag_old[rt]=max(tag_old[rt],tag_now[rt]+=add);
max_old[rt]=max(max_old[rt],max_now[rt]+=add);
return ;
}
// if(rt==14)printf("%d\n",tag_old[rt]);
PushDown(l,r,rt);
creatmid;
if(mid>=R)update(L,R,add,lson);
else if(mid<L)update(L,R,add,rson);
else
{
update(L,R,add,lson);
update(L,R,add,rson);
}
PushUp(rt);
}
ll query(int L,int R,int l,int r,int rt)
{
// printf("L=%d R=%d l=%d r=%d rt=%d old=%lld\n",L,R,l,r,rt,max_old[rt]);
if(l>=L && r<=R)return max_old[rt];
PushDown(l,r,rt);
creatmid;
if(mid>=R)return query(L,R,lson);
if(mid<L)return query(L,R,rson);
return max(query(L,R,lson),query(L,R,rson));
}
int main()
{
int i;
scanf("%d",&n);
rep(i,n)
scanf("%lld",&a[i]);
scanf("%d",&q);
rep(i,q)
{
scanf("%d%d",&Q[i].L,&Q[i].R);
Q[i].id=i;
}
sort(Q,Q+q+1);
// rep(i,q)
// printf("L=%d R=%d\n",Q[i].L,Q[i].R);
int num=1;
rep(i,n)
{
update(pos[a[i]+N]+1,i,a[i],1,n,1);
pos[a[i]+N]=i;
for(;Q[num].R==i && num<=q;num++)
ans[Q[num].id]=query(Q[num].L,Q[num].R,1,n,1);
if(num>q)break;
}
// printf("%d\n",tag_old[8]);
rep(i,q)
printf("%lld\n",ans[i]);
return 0;
}
---恢复内容结束---
GSS2-Can you answer these queries II的更多相关文章
- SPOJ GSS2 - Can you answer these queries II(线段树 区间修改+区间查询)(后缀和)
GSS2 - Can you answer these queries II #tree Being a completist and a simplist, kid Yang Zhe cannot ...
- bzoj 2482: [Spoj GSS2] Can you answer these queries II 线段树
2482: [Spoj1557] Can you answer these queries II Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 145 ...
- spoj gss2 : Can you answer these queries II 离线&&线段树
1557. Can you answer these queries II Problem code: GSS2 Being a completist and a simplist, kid Yang ...
- SPOJ GSS2 Can you answer these queries II
Time Limit: 1000MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Description Being a ...
- SPOJ1557 GSS2 Can you answer these queries II 历史最值线段树
传送门 题意:给出一个长度为$N$的数列,$Q$次询问,每一次询问$[l,r]$之间的最大子段和,相同的数只计算一次.所有数字的绝对值$\leq 10^5$ GSS系列中不板子的大火题,单独拿出来写 ...
- SP1557 GSS2 - Can you answer these queries II
一开始看不懂题解,看懂了题解之后觉得还是挺妙的. 好多题解里都提到了HH的项链,但是我觉得关系并不大啊…… 先把所有询问离线下来按照右端点排序,按照询问的要求一个一个加入数字,怎么加入数字,我们设计一 ...
- SPOJ GSS2 Can you answer these queries II ——线段树
[题目分析] 线段树,好强! 首先从左往右依次扫描,线段树维护一下f[].f[i]表示从i到当前位置的和的值. 然后询问按照右端点排序,扫到一个位置,就相当于查询区间历史最值. 关于历史最值问题: 标 ...
- SP1557 GSS2 - Can you answer these queries II(线段树)
传送门 线段树好题 因为题目中相同的只算一次,我们可以联想到HH的项链,于是考虑离线的做法 先把所有的询问按$r$排序,然后每一次不断将$a[r]$加入线段树 线段树上维护四个值,$sum,hix,s ...
- SPOJ 1557 GSS2 - Can you answer these queries II (线段树+维护历史最值)
都说这题是 GSS 系列中最难的,今天做了一下,名副其实 首先你可以想到各种各样的在线乱搞想法,线段树,主席树,平衡树,等等,但发现都不太可行. 注意到题目也没有说强制在线,因此可以想到离线地去解决这 ...
- BZOJ2482: [Spoj1557] Can you answer these queries II
题解: 从没见过这么XXX的线段树啊... T_T 我们考虑离线做,按1-n一个一个插入,并且维护区间[ j,i](i为当前插入的数)j<i的最优值. 但这个最优值!!! 我们要保存历史的最优值 ...
随机推荐
- Http Clinet使用
Http Client是个apache下的一个开源包,用于使用http协议访问服务的java代码编写. Http Client的主要功能: (1)实现了所有 HTTP 的方法(GET,POST,PUT ...
- Session与Cookie间不得不说的一些事
在很久很久以前,刚有浏览器和网页的时候,web开发者发现了一个问题,我必须要在客户端这边保存一些东西才能实现某些功能,比如大家喜闻乐见的购物车.用户登录.自动登陆等.但是客户端只有一个浏览器,怎么在用 ...
- 一句SQL实现MYSQL的递归查询
众所周知,目前的mysql版本中并不支持直接的递归查询,但是通过递归到迭代转化的思路,还是可以在一句SQL内实现树的递归查询的.这个得益于Mysql允许在SQL语句内使用@变量.以下是示例代码. 创建 ...
- Halloween party
https://www.hackerrank.com/challenges/halloween-party def main(): t = int(raw_input()) for _ in rang ...
- 提交 应用ID 证书
https://developer.apple.com/account/ios/profile/profileCreate.action?formID=960914622
- OC与Swift混编
群里大神发的网址,感觉有用就先收录了,暂时没时间看SWIFT,感觉代码简洁,但是可阅读性不是太高,有些代码让系统去判断类型,同样的,我们看代码的时候也得自己去判断类型,或许看多就习惯了,有时间再说吧, ...
- 升级10.11后使用CocoaPod出现-bash: pod: command not found 解决办法-备
升级10.11后,运行pod命令出现: -bash: pod: command not found 解决办法: sudo gem install -n /usr/local/bin cocoapods ...
- XJOI网上同步训练DAY2 T1
[问题描述] 为了迎接校庆月亮中学操场开始施工.不久后操场下发现了很多古墓这些古墓中有很多宝藏.然而学生们逐渐发现自从操场施工之后学校的运气就开始变得特别不好.后来经过调查发现古墓下有一个太守坟由于操 ...
- AT89C 系列单片机解密原理
单片机解密简单就是擦除单片机片内的加密锁定位.由于AT89C系列单片机擦除操作时序设计上的不合理.使在擦除片内程序之前首先擦除加密锁定位成为可能.AT89C系列单片机擦除操作的时序为:擦除开始---- ...
- 新版TeamTalk部署教程(蓝狐)
http://www.bluefoxah.org/teamtalk/new_tt_deploy.html