• cf765F.Souvenirs


    比赛的时候看错了C题于是不会做了……来搞F,听说有人莫队水过去了,于是也写了个莫队,TLE7……惨掉rating

    editorial看得很烦躁啊……又回想起了被英语阅读支配的恐惧

    离线,移动右端点,考虑维护左端点处的答案.设当前右端点移动到了i,数列为a[],则答案的更新一定是由a[i]与某些a[j](j<i)的差的绝对值引起的,下面只考虑a[j]≥a[i]的情况,a[j]≤a[i]同理(当然如果有a[j]=a[i]会被用来更新2次但是肯定不会影响答案正确性)

    首先我们找出最大的一个j满足j<i,a[j]≥a[i],用它更新[1,j]的答案。设a[j]=y,那么在[1,j-1]中如果有a的值大于y,肯定不会对答案构成影响(因为它与a[i]的差大于a[j]-a[i]),实际上,我们发现对于a数列中任何一个位于[1,j-1]的数,当且仅当它处于[a[i],(a[i]+a[j])/2]时,才可能与a[i]成对,对前面的答案造成影响,如果一个元素的值位于((a[i]+a[j])/2,a[j]],那么它肯定会与a[j]成对。这样一来,我们就把需要考虑的值域从[a[i],1e9]缩短到了[a[i],(a[i]+a[j])/2],重复这个过程,每次都至少会把这个区间折半,于是更新答案的次数是O(log(1e9))的,更新答案的过程用一个区间取min的线段树维护,寻找某一值域中最右元素可用一个动态开点的权值线段树维护,于是总时间复杂度为O(nlog2MaxV+mlogn),如果把a[]离散化之后开权值线段树可以做到O(nlognlogMaxV+mlogn),其中MaxV=1e9.

      1 program cf765F;
      2 uses math;
      3 const maxn=100000+10;
      4       maxm=300000+10;
      5       maxv=1000000000;
      6 type query=record next,l,r:longint;end;
      7 var a,last:array[0..maxn] of longint;
      8     ques:array[0..maxm] of query;
      9     ans:array[0..maxm] of longint;
     10     mark:array[0..maxn*4] of longint;
     11     segv:array[0..maxn*40] of record l,r,right:longint;end;
     12     n,m,root,tot,i,j,l,r,id:longint;
     13 procedure build(x,l,r:longint);
     14 var mid:longint;
     15 begin
     16   mark[x]:=maxv+1;
     17   if l<r then
     18   begin
     19     mid:=(l+r)shr 1;
     20     build(x+x,l,mid);
     21     build(x+x+1,mid+1,r);
     22   end;
     23 end;
     24 procedure update(x,l,r,nowl,nowr,v:longint);
     25 var mid:longint;
     26 begin
     27   if(nowl<=l)and(r<=nowr) then
     28   begin
     29     mark[x]:=min(mark[x],v);
     30     exit;
     31   end;
     32   mid:=(l+r)shr 1;
     33   if nowl<=mid then update(x+x,l,mid,nowl,nowr,v);
     34   if nowr>mid then update(x+x+1,mid+1,r,nowl,nowr,v);
     35 end;
     36 function ask(x,l,r,p:longint):longint;
     37 var mid:longint;
     38 begin
     39   if l=r then exit(mark[x]);
     40   mid:=(l+r)shr 1;
     41   if p<=mid then exit(min(mark[x],ask(x+x,l,mid,p)))
     42     else exit(min(mark[x],ask(x+x+1,mid+1,r,p)));
     43 end;
     44 function findright(x,l,r,nowl,nowr:longint):longint;
     45 var mid:longint;
     46 begin
     47   if((nowl<=l)and(r<=nowr))or(x=0) then exit(segv[x].right);
     48   mid:=(l+r)shr 1;
     49   if nowr<=mid then exit(findright(segv[x].l,l,mid,nowl,nowr));
     50   if nowl>mid then exit(findright(segv[x].r,mid+1,r,nowl,nowr));
     51   exit(max(findright(segv[x].l,l,mid,nowl,nowr),findright(segv[x].r,mid+1,r,nowl,nowr)));
     52 end;
     53 procedure modify(var x:longint;l,r,p,v:longint);
     54 var mid:longint;
     55 begin
     56   if x=0 then
     57   begin
     58     inc(tot);
     59     x:=tot;
     60   end;
     61   segv[x].right:=max(segv[x].right,v);
     62   if l<r then
     63   begin
     64     mid:=(l+r)shr 1;
     65     if p<=mid then modify(segv[x].l,l,mid,p,v)
     66       else modify(segv[x].r,mid+1,r,p,v);
     67   end;
     68 end;
     69 begin
     70   readln(n);
     71   for i:=1 to n do read(a[i]);
     72   readln(m);
     73   for i:=1 to m do readln(ques[i].l,ques[i].r);
     74   fillchar(last,sizeof(last),0);
     75   for i:=1 to m do
     76   begin
     77     ques[i].next:=last[ques[i].r];
     78     last[ques[i].r]:=i;
     79   end;
     80   build(1,1,n);
     81   root:=0;
     82   tot:=0;
     83   segv[0].right:=0;
     84   for i:=1 to n do
     85   begin
     86     if i>1 then
     87     begin
     88       l:=a[i];
     89       r:=maxv;
     90       while true do
     91       begin
     92         id:=findright(root,0,maxv,l,r);
     93         if id=0 then break;
     94         update(1,1,n,1,id,a[id]-a[i]);
     95         if a[i]=a[id] then break;
     96         r:=(a[i]+a[id])shr 1;
     97       end;
     98       l:=0;
     99       r:=a[i];
    100       while true do
    101       begin
    102         id:=findright(root,0,maxv,l,r);
    103         if id=0 then break;
    104         update(1,1,n,1,id,a[i]-a[id]);
    105         if a[i]=a[id] then break;
    106         l:=(a[i]+a[id])shr 1+1;
    107       end;
    108     end;
    109     j:=last[i];
    110     while j>0 do
    111     begin
    112       ans[j]:=ask(1,1,n,ques[j].l);
    113       j:=ques[j].next;
    114     end;
    115     modify(root,0,maxv,a[i],i);
    116   end;
    117   for i:=1 to m do writeln(ans[i]);
    118 end.
    View Code
  • 相关阅读:
    Cornerstone-忽略(隐藏)文件
    ios开发xcode8+ 无需开发者账号,app打包ipa
    ssh-ajax登陆action返回字符串
    手动编译包含两个import自写类的java类。
    关闭IO资源
    java聊天室二(客户端)
    java聊天室一(服务器)
    文件IO常用操作
    Hive启动时的棘手问题的处理
    对于java反射的理解
  • 原文地址:https://www.cnblogs.com/lkmcfj/p/6413726.html
Copyright © 2020-2023  润新知