Can you answer these queries II

本文介绍了一种利用线段树解决特定区间内最大去重连续子段和问题的方法。通过预处理和线段树维护,实现了对每个查询区间的高效处理,最终达到O(nlogn)的时间复杂度。

题意:

给一长度为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

Score : 350 points    Problem Statement On the poker table, there are tea bags of N different flavors. The flavors are numbered from 1 through N, and there are A i ​ tea bags of flavor i ( 1≤i≤N). You will play a game using these tea bags. The game has a parameter called difficulty between 1 and A 1 ​ +⋯+A N ​ , inclusive. A game of difficulty b proceeds as follows: You declare an integer x. Here, it must satisfy b≤x≤A 1 ​ +⋯+A N ​ . The dealer chooses exactly x tea bags from among those on the table and gives them to you. You check the flavors of the x tea bags you received, and choose b tea bags from them. If all b tea bags you chose are of the same flavor, you win. Otherwise, you lose. The dealer will do their best to make you lose. You are given Q queries, so answer each of them. The j-th query is as follows: For a game of difficulty B j ​ , report the minimum integer x you must declare at the start to guarantee a win. If it is impossible to win, report −1 instead. DeepL 翻译    问题陈述 扑克桌上有 N 种不同口味的茶包。这些茶包的编号从 1 到 N ,其中有 A i ​ 个茶包的口味是 i ( 1≤i≤N )。 您将用这些茶包做一个游戏。游戏的参数为难度,介于 1 和 A 1 ​ +⋯+A N ​ 之间。难度为 b 的游戏过程如下: 你声明一个整数 x 。这里,它必须满足 b≤x≤A 1 ​ +⋯+A N ​ 。 庄家从桌子上的茶包中恰好选出 x 个茶包给你。 你检查你收到的 x 袋泡茶的味道,从中选择 b 袋泡茶。 如果你选择的所有 b 茶叶都是同一种口味,你就赢了。否则,你输了。 庄家会尽力让你输。 你会得到 Q 个问题,请逐一回答。 j 个问题如下: 对于难度为 B j ​ 的游戏,请报告你必须在游戏开始时宣布的保证获胜的最小整数 x 。如果不可能获胜,则报告 −1 。    Constraints 1≤N≤3×10 5 1≤Q≤3×10 5 1≤A i ​ ≤10 6 ( 1≤i≤N) 1≤B j ​ ≤min(10 6 ,A 1 ​ +⋯+A N ​ ) ( 1≤j≤Q) All input values are integers. DeepL 翻译    限制因素 1≤N≤3×10 5 1≤Q≤3×10 5 1≤A i ​ ≤10 6 ( 1≤i≤N ) 1≤B j ​ ≤min(10 6 ,A 1 ​ +⋯+A N ​ ) ( 1≤j≤Q ) 所有输入值均为整数。    Input The input is given from Standard Input in the following format: N Q A 1 ​ ⋯ A N ​ B 1 ​ ⋮ B Q ​ DeepL 翻译    输入 输入内容由标准输入法提供,格式如下 N Q A 1 ​ ⋯ A N ​ B 1 ​ ⋮ B Q ​    Output Print Q lines. The j-th line ( 1≤j≤Q) should contain the answer to the j-th query. DeepL 翻译    输出 打印 Q 行。 j -th 行( 1≤j≤Q )应包含对 j -th 查询的回答。    Sample Input 1 Copy 4 5 4 1 8 4 1 8 5 2 10 DeepL 翻译    输入样本 1 4 5 4 1 8 4 1 8 5 2 10    Sample Output 1 Copy 1 17 14 5 -1 For the 1-st query, if you declare x=1, then no matter which 1 bag the dealer chooses, you can satisfy the winning condition by choosing appropriate 1 bag among them. Since you cannot choose an integer x less than 1, the answer is 1. For the 2-nd query, if you declare x=17, then no matter which 17 bags the dealer chooses, you can satisfy the winning condition by choosing appropriate 8 bags among them. Conversely, if x<17, the dealer can choose bags to prevent your victory. Thus, the answer is 17. For the 3-rd query, if you declare x=14, then no matter which 14 bags the dealer chooses, you can satisfy the winning condition by choosing appropriate 5 bags among them. Conversely, if x<14, the dealer can choose bags to prevent your victory. Thus, the answer is 14. For the 4-th query, if you declare x=5, then no matter which 5 bags the dealer chooses, you can satisfy the winning condition by choosing appropriate 2 bags among them. Conversely, if x<5, the dealer can choose bags to prevent your victory. Thus, the answer is 5. For the 5-th query, no matter what x you declare, the dealer can choose bags to prevent your victory. Thus, print −1. DeepL 翻译    样本输出 1 1 17 14 5 -1 对于 1 -st疑问句,如果你声明 x=1 ,那么无论庄家选择哪一个 1 包,你都可以通过在其中选择合适的 1 包来满足获胜条件。由于你不能选择小于 1 的整数 x ,所以答案是 1 。 对于 2 /nd这个疑问句,如果你声明 x=17 ,那么无论庄家选择哪一个 17 包,你都可以通过在其中选择适当的 8 包来满足获胜条件。反之,如果 x<17 ,庄家可以选择袋子阻止你获胜。因此,答案是 17 。 对于 3 (rd)这个疑问句,如果你宣布 x=14 ,那么无论庄家选择哪一个 14 包,你都可以通过在其中选择适当的 5 包来满足获胜条件。反之,如果 x<14 ,庄家可以选择袋子阻止你获胜。因此,答案是 14 。 对于 4 -th这个疑问句,如果你宣布 x=5 ,那么无论庄家选择哪一个 5 个袋子,你都可以通过在其中选择适当的 2 个袋子来满足获胜条件。反之,如果 x<5 ,庄家可以选择袋子阻止你获胜。因此,答案是 5 。 对于 5 -th这个疑问句,无论你下出什么 x ,庄家都可以选择袋子来阻止你获胜。因此,请打印 −1 。    Sample Input 2 Copy 5 3 13 13 13 13 2 5 12 13 DeepL 翻译    输入样本 2 5 3 13 13 13 13 2 5 12 13    Sample Output 2 Copy 19 47 51 DeepL 翻译    输出示例 2 19 47 51
最新发布
08-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值