题意:

给一长度为n的序列,有m组询问,每一组询问给出[l,r]询问区间内的最大去重连续子段和。

解法:

考虑一下简化后的问题:如果题目要求询问查询以$r$为右端点且$l$大于等于给定值的去重连续子段和,

那么我们显然可以预处理出$pre(i)$表示$i$位置出现的数字上一次出现的位置。

那么我们可以从小到大枚举$r$,

线段树维护$[i,r]$的去重子段和,区间加+维护最大值进而求出$[i,r]$的去重子段和的最大值。

现在考虑r小于等于给定值的做法,

注意到r是从1开始到n枚举的,进而保证了线段树里出现过的值都是$[l_i,r_i],r_i<=r$的去重子段和。

所以我们只要维护一下历史上线段树$i$位置出现过的历史最大值即可。

注意区间加的$add$标记不可以简单的合并,

因为我们要求的是历史上出现过的最大值,有可能$add 2, add -2$两个标记合并为$add 0$,进而错过最优答案。

对于一个点的$add$操作可以认为是一个$add$的序列,

我们要维护$add$序列中出现过的最大的前缀和,类比经典的处理方法最大子段和。

注意到线段树要维护4个标记:

历史最大值

当前最大值

当前$add$

$add$序列里的最大前缀和

总效率$O(nlogn)$

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <map>
  5 #include <algorithm>
  6
  7 #define N 100010
  8 #define l(x) ch[x][0]
  9 #define r(x) ch[x][1]
 10 #define LL long long
 11 #define INF 0x3f3f3f3f
 12
 13 using namespace std;
 14
 15 struct node
 16 {
 17     int l,r,id;
 18 }b[N];
 19
 20 int n,totn,m;
 21 int a[N],pre[N],a0[N];
 22 int ch[N<<1][2];
 23 LL max_all[N<<1],maxv[N<<1];
 24 LL add_all[N<<1],addv[N<<1];
 25 LL ansv[N];
 26 map<int,int> pos;
 27
 28 bool cmp(node a,node b)
 29 {
 30     return a.r<b.r;
 31 }
 32
 33 void push(int x)
 34 {
 35     if(!addv[x] && !add_all[x]) return;
 36     add_all[l(x)]=max(add_all[l(x)],addv[l(x)]+max(add_all[x],0LL));
 37     max_all[l(x)]=max(max_all[l(x)],maxv[l(x)]-addv[l(x)]+max(add_all[l(x)],0LL));
 38     addv[l(x)]+=addv[x];
 39     maxv[l(x)]+=addv[x];
 40
 41     add_all[r(x)]=max(add_all[r(x)],addv[r(x)]+max(add_all[x],0LL));
 42     max_all[r(x)]=max(max_all[r(x)],maxv[r(x)]-addv[r(x)]+max(add_all[r(x)],0LL));
 43     addv[r(x)]+=addv[x];
 44     maxv[r(x)]+=addv[x];
 45     addv[x]=0;
 46     add_all[x]=0;
 47 }
 48
 49 void update(int x)
 50 {
 51     maxv[x]=max(maxv[l(x)],    maxv[r(x)]);
 52     max_all[x]=max(max_all[x],max_all[l(x)]);
 53     max_all[x]=max(max_all[x],max_all[r(x)]);
 54 }
 55
 56 LL ask(int x,int l,int r,int ql,int qr)
 57 {
 58     push(x);
 59     if(ql<=l && r<=qr) return max_all[x];
 60     int mid=(l+r)>>1;
 61     LL ans=0;
 62     if(ql<=mid) ans = max(ans, ask(l(x),l,mid,ql,qr));
 63     if(mid<qr)  ans = max(ans, ask(r(x),mid+1,r,ql,qr));
 64     update(x);
 65     return ans;
 66 }
 67
 68 void add(int x,int l,int r,int ql,int qr,LL qv)
 69 {
 70     push(x);
 71     if(ql<=l && r<=qr)
 72     {
 73         addv[x]=qv;
 74         add_all[x]=max(qv,0LL);
 75         maxv[x]+=qv;
 76         max_all[x]=max(max_all[x],maxv[x]);
 77         return;
 78     }
 79     int mid=(l+r)>>1;
 80     if(ql<=mid) add(l(x),l,mid,ql,qr,qv);
 81     if(mid<qr) add(r(x),mid+1,r,ql,qr,qv);
 82     update(x);
 83 }
 84
 85 int build(int l,int r)
 86 {
 87     int x=++totn;
 88     max_all[x]=maxv[x]=0;
 89     add_all[x]=0;
 90     addv[x]=0;
 91     if(l==r) return x;
 92     int mid=(l+r)>>1;
 93     l(x)=build(l,mid);
 94     r(x)=build(mid+1,r);
 95     return x;
 96 }
 97
 98 int main()
 99 {
100     while(~scanf("%d",&n))
101     {
102         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
103         scanf("%d",&m);
104         for(int i=1;i<=m;i++)
105         {
106             scanf("%d%d",&b[i].l,&b[i].r);
107             b[i].id=i;
108         }
109         sort(b+1,b+m+1,cmp);
110         totn=0;
111         pos.clear();
112         for(int i=1;i<=n;i++)
113         {
114             if(pos.count(a[i])) pre[i]=pos[a[i]];
115             else pre[i]=0,a0[i]=a[i];
116             pos[a[i]]=i;
117         }
118         build(1,n);
119         int j=1;
120         for(int i=1;i<=n;i++)
121         {
122             add(1,1,n,pre[i]+1,i,a[i]);
123             while(j<=m && b[j].r==i)
124             {
125                 ansv[b[j].id]=ask(1,1,n,b[j].l,b[j].r);
126                 j++;
127             }
128         }
129         for(int i=1;i<=m;i++)
130             printf("%lld\n",ansv[i]);
131     }
132     return 0;
133 }

View Code

转载于:https://www.cnblogs.com/lawyer/p/6530517.html

Can you answer these queries II相关推荐

  1. SPOJ GSS2 Can you answer these queries II (线段树离线) - xgtao -

    Can you answer these queries II 这是一道线段树的题目,维护历史版本,给出N(<=100000)个数字(-100000<=x<=100000),要求求出 ...

  2. GSS2 - Can you answer these queries II

    GSS2 - Can you answer these queries II 题意: 给你1e51e51e5 的序列,每次询问区间l到rl到rl到r,每个相同的数只算一次的最大子段和. 思路: 乍一眼 ...

  3. SP1557 GSS2 - Can you answer these queries II

    一开始看不懂题解,看懂了题解之后觉得还是挺妙的. 好多题解里都提到了HH的项链,但是我觉得关系并不大啊-- 先把所有询问离线下来按照右端点排序,按照询问的要求一个一个加入数字,怎么加入数字,我们设计一 ...

  4. SPOJ GSS2 Can you answer these queries II

    很好的一道题,想了很久.首先突破的是,可以找到枚举其中一边,假设是尾部y,然后快速找出满足条件的最大的头部x,连续区间的和 很容易想到借助部分和的思想,如果是从y开始往前面累加,那么就是一个关于y的后 ...

  5. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  6. 线性代数四之动态DP(广义矩阵加速)——Can you answer these queries III,保卫王国

    动态DP--广义矩阵加速 SP1716 GSS3 - Can you answer these queries III description solution code [NOIP2018 提高组] ...

  7. HDU 4027 Can you answer these queries?(线段树/区间不等更新)

    传送门 Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/6576 ...

  8. HDU 1027 G - Can you answer these queries?

    http://acm.hdu.edu.cn/showproblem.php?pid=4027 Can you answer these queries? Time Limit: 4000/2000 M ...

  9. Can you answer these queries I SPOJ - GSS1 (线段树维护区间连续最大值/最大连续子段和)...

    You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). A query is defi ...

最新文章

  1. GitHub上共享的简单易用 TensorFlow 代码集
  2. 安卓高手之路之ClassLoader(四)
  3. go语音protobuf_golang 使用 protobuf 的教程
  4. 2021-07-27 详解TCP连接建立和释放的过程(三报文握手和四次挥手)
  5. java se拖动插件_JQuery之拖拽插件
  6. 复制一个空洞文件且忽略掉其空洞内容
  7. 每天CookBook之JavaScript-073
  8. Asp.net 后台添加Meta标签方法
  9. CSDN账号被盗了吗?
  10. java同步锁-详细易懂
  11. postman小技巧-提取变量及设置变量
  12. php v9验证码错误,phpcms后台显示验证码错误怎么办
  13. 唐巧:技术人如何成为管理者
  14. 平面设计简化布局的要点是什么
  15. 我的简约论坛php源码,我的论坛源代码(二)
  16. 分享几个我常用渗透网站
  17. python 怎么实现3d 动画_python – 使用matplotlib的3D动画
  18. 页面地址index.html,分析首页链接:/和/index.html
  19. canvas实现一个线性图
  20. 控制系统Matlab仿真——校正

热门文章

  1. rpm 安装 忽略依赖_rpm 解决依赖的方法
  2. 怎么引jsp包_电机引接线的制作流程防护等级
  3. 通俗解释glLoadIdentity(),glPushMatrix(),glPopMatrix()的作用 (
  4. Qt工作笔记-QString中arg的使用(可用于SQL语句拼接)
  5. ajax视频播放,XMLHttpRequest加载视频并播放
  6. 周期均方根和有效值的区别_如何判断化学锚栓和膨胀锚栓的区别
  7. js 字符串插入_Vue.js 条件与循环
  8. nginx 防止恶意域名解析_配置nginx只允许域名访问,禁止ip访问【图文教程】
  9. python读取lmdb文件_如何使用python創建LMDB文件
  10. java传输文件暂停_java – 在文件下载中实现暂停/恢复