bzoj2653

本文详细介绍了如何利用二分答案和线段树技术来解决区间和问题,通过建立线段树并进行快速查询与更新操作,实现对大量数据的高效处理。具体步骤包括:首先将问题转化为判定性问题,然后通过二分搜索找到满足条件的区间,并利用线段树结构快速计算区间和。此方法适用于多种场景,特别在需要频繁查询和更新区间和的情况下展现出其优越性。
摘要由CSDN通过智能技术生成

CLJ神牛的可持久化论文的题目,果然厉害
其实第一步能想到后面就还是很简单的
首先是二分答案,转化为判定性问题
然后对于区间内的数,比他大的标为1,小的标为-1
显然,如果存在一个左右端点符合的区间使得这个区间和大于等于0(因为这里中位数是向下取整)
那么中位数一定是大于等于这个数的,这并不难理解
下面我们就是要快速求出左端点在[a,b],右端点[c,d]的最大区间和
显然可以转化为rmax[a,b]+sum[b+1,c-1]+lmax[c,d];
这里我们不难想到对于每个数建立一个线段树
线段树就是以位置为索引的,记录着区间左最大,区间右最大和区间和
考虑到树的形态都是相同的,我们可以先对数进行排序,然后建立主席树
平时我们的主席树都是在每个位置上建立一棵以键值为索引的线段树,而这里刚好相反
二分答案后就对对应数的线段树求区间最大和

  1 type node=record
  2        lm,rm,l,r,s:longint;
  3      end;
  4 
  5 var tree:array[0..20010*20] of node;
  6     a,c,h:array[0..20010] of longint;
  7     q:array[0..4] of longint;
  8     j,m,t,ans,n,mid,i,l,r,w:longint;
  9 
 10 function max(a,b:longint):longint;
 11   begin
 12     if a>b then exit(a) else exit(b);
 13   end;
 14 
 15 procedure swap(var a,b:longint);
 16   var c:longint;
 17   begin
 18     c:=a;
 19     a:=b;
 20     b:=c;
 21   end;
 22 
 23 procedure deal;
 24   var i,j:longint;
 25   begin
 26     for i:=1 to 3 do
 27       for j:=i+1 to 4 do
 28         if q[i]>q[j] then swap(q[i],q[j]);
 29   end;
 30 
 31 procedure sort(l,r: longint);
 32   var i,j,x,y: longint;
 33   begin
 34     i:=l;
 35     j:=r;
 36     x:=a[(l+r) shr 1];
 37     repeat
 38       while a[i]<x do inc(i);
 39       while x<a[j] do dec(j);
 40       if not(i>j) then
 41       begin
 42         swap(c[i],c[j]);
 43         swap(a[i],a[j]);
 44         inc(i);
 45         j:=j-1;
 46       end;
 47     until i>j;
 48     if l<j then sort(l,j);
 49     if i<r then sort(i,r);
 50   end;
 51 procedure update(var a,b,c:node);
 52   begin
 53     a.s:=b.s+c.s;
 54     a.lm:=max(b.lm,b.s+c.lm);
 55     a.rm:=max(c.rm,c.s+b.rm);
 56   end;
 57 
 58 function build(l,r:longint):longint;
 59   var m,q:longint;
 60   begin
 61     inc(t);
 62     if l=r then
 63     begin
 64       tree[t].s:=1;
 65       tree[t].lm:=1;
 66       tree[t].rm:=1;
 67       exit(t);
 68     end
 69     else begin
 70       m:=(l+r) shr 1;
 71       q:=t;
 72       tree[q].l:=build(l,m);
 73       tree[q].r:=build(m+1,r);
 74       update(tree[q],tree[tree[q].l],tree[tree[q].r]);
 75       exit(q);
 76     end;
 77   end;
 78 
 79 function work(l,r,last,x:longint):longint;
 80   var m,q:longint;
 81   begin
 82     inc(t);
 83     if l=r then
 84     begin
 85       tree[t].s:=-1;
 86       tree[t].lm:=-1;
 87       tree[t].rm:=-1;
 88       exit(t);
 89     end
 90     else begin
 91       m:=(l+r) shr 1;
 92       q:=t;
 93       if x<=m then
 94       begin
 95         tree[q].r:=tree[last].r;
 96         tree[q].l:=work(l,m,tree[last].l,x);
 97       end
 98       else begin
 99         tree[q].l:=tree[last].l;
100         tree[q].r:=work(m+1,r,tree[last].r,x);
101       end;
102       update(tree[q],tree[tree[q].l],tree[tree[q].r]);
103       exit(q);
104     end;
105   end;
106 
107 function ask(l,r,x,ql,qr:longint):node;  //传递整个node的的写法比我以前的写法要简单不少
108   var m:longint;
109       s,s1,s2:node;
110   begin
111     s.lm:=0;  s.rm:=0;    s.s:=0;
112     if ql>qr then exit(s);
113     if (ql<=l) and (qr>=r) then exit(tree[x])
114     else begin
115       m:=(l+r) shr 1;
116       if ql>m then exit(ask(m+1,r,tree[x].r,ql,qr));
117       if qr<=m then exit(ask(l,m,tree[x].l,ql,qr));
118       s1:=ask(l,m,tree[x].l,ql,qr);
119       s2:=ask(m+1,r,tree[x].r,ql,qr);
120       update(s,s1,s2);
121       exit(s);
122     end;
123   end;
124 
125 begin
126   readln(n);
127   for i:=1 to n do
128   begin
129     readln(a[i]);
130     c[i]:=i;
131   end;
132   sort(1,n);
133   h[1]:=build(1,n);
134   for i:=2 to n do
135     h[i]:=work(1,n,h[i-1],c[i-1]);
136   readln(m);
137   for i:=1 to m do
138   begin
139     for j:=1 to 4 do
140     begin
141       read(q[j]);
142       q[j]:=(q[j]+ans) mod n+1;
143     end;
144     readln;
145     deal;
146     l:=1;
147     r:=n;
148     while l<=r do  //二分答案
149     begin
150       mid:=(l+r) shr 1;
151       w:=ask(1,n,h[mid],q[1],q[2]).rm+ask(1,n,h[mid],q[3],q[4]).lm+ask(1,n,h[mid],q[2]+1,q[3]-1).s;
152       if w>=0 then
153       begin
154         ans:=a[mid];
155         l:=mid+1;
156       end
157       else r:=mid-1;
158     end;
159     writeln(ans);
160   end;
161 end.
View Code

 

转载于:https://www.cnblogs.com/phile/p/4473053.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值