zoukankan      html  css  js  c++  java
  • bzoj4826: [Hnoi2017]影魔

    唯一一道赛场上a掉的题……

    首先考虑第一种贡献。先不考虑两个相邻的情况,这个我们可以查询的时候直接加。首先预处理出第i个数左边离他最近的比他大的数的位置l[i],以及右边的r[i](这个可以用单调栈做,我用的树状数组),如果l[i]和r[i]存在,那么以第i个数为为他们最大值的点对只有(l[i],r[i])。这样的话点对数量是O(n)的,我们每次查询区间[L,R]的第一类贡献,除了相邻的情况,就是查询有多少个点对在[L ,R]之间,这个是个二维矩形求值可以主席树来轻松的维护。

    对于第二种贡献,考虑一开始求出的l[i],r[i]数组。那么如果有l[i]<x<i,那么(x,r[i])一定是满足第二类贡献且他们之间最大值为a[i](因为显然有x<a[i],a[i]<a[r[i]])。对于i<x<r[i]也是一样的情况。那么我们单考虑r[i]的情况,对于查询[L,R],就是查询所有l<=r[i]<=r的min(r[i],R)-max(l[i],L),就是说对于我们每一个枚举的最大值,找到l[i],r[i],在二维空间中覆盖两条线段(r[i],l[i]+1)到(r[i],i-1)和(l[i],i+1)到(l[i],r[i]-1),查询的时候也是做一个二维矩形求值,这个也可可以主席树来做,相当于打个tag,不过最好不要下传做个标记永久化

    然后就没有了,时间复杂度O(nlogn),我没开int64也过了,数据都是随机的吧2333没有卡真是万幸

    然后代码非常丑……考场上写了一半觉得写得不简洁就改改改……结果还是一大坨……

      1 //orz lzz,you are our red sun
      2 program j01;
      3 const maxn=200086;
      4 type node=record l,r,tag,sum:longint; end;
      5      opr=record l,r,ps:longint; end;
      6      opr1=record l,r,id:longint;end;
      7 var f:array[0..80*maxn]of node;
      8     root1,root2:array[0..maxn]of longint;
      9     op1:array[0..maxn]of opr1;
     10     op:array[0..2*maxn]of opr;
     11     p,c:array[0..maxn]of longint;
     12     n,m,p1,p2,l,r,i,tt,inf,j,tot,ll,rr:longint;
     13     ans:int64;
     14     a:array[0..maxn]of longint;
     15 
     16 function max(a,b:longint):longint;inline;
     17 begin
     18     if a>b then exit(a) else exit(b);
     19 end;
     20 
     21 function min(a,b:longint):longint;inline;
     22 begin
     23     if a<b then exit(a) else exit(b);
     24 end;
     25 
     26 procedure insmx(i,dd:longint);
     27 begin
     28     while i<=n do
     29     begin
     30         c[i]:=max(c[i],dd);i:=i+(i and(-i));
     31     end;
     32 end;
     33 
     34 function askmx(i:longint):longint;
     35 var tmp:longint;
     36 begin
     37     tmp:=0;
     38     while i>0 do
     39     begin
     40         tmp:=max(tmp,c[i]);i:=i-(i and(-i));
     41     end;
     42     exit(tmp);
     43 end;
     44 
     45 procedure insmn(i,dd:longint);
     46 begin
     47     while i<=n do
     48     begin
     49         c[i]:=min(c[i],dd);i:=i+(i and(-i));
     50     end;
     51 end;
     52 
     53 function askmn(i:longint):longint;
     54 var tmp:longint;
     55 begin
     56     tmp:=inf;
     57     while i>0 do
     58     begin
     59         tmp:=min(tmp,c[i]);i:=i-(i and(-i));
     60     end;
     61     exit(tmp);
     62 end;
     63     
     64 procedure sort1(l,r:longint);
     65 var i,j,x:longint;y:opr1;
     66 begin
     67     i:=l;j:=r;x:=op1[(i+j)div 2].l;
     68     repeat
     69         while op1[i].l<x do inc(i);
     70         while x<op1[j].l do dec(j);
     71         if i<=j then
     72         begin
     73             y:=op1[i];op1[i]:=op1[j];op1[j]:=y;
     74             inc(i);dec(j);
     75         end;
     76     until i>j;
     77     if i<r then sort1(i,r);
     78     if l<j then sort1(l,j);
     79 end;
     80 
     81 procedure sort(l,r:longint);
     82 var i,j,x:longint;y:opr;
     83 begin
     84     i:=l;j:=r;x:=op[(i+j)div 2].ps;
     85     repeat
     86         while op[i].ps<x do inc(i);
     87         while x<op[j].ps do dec(j);
     88         if i<=j then
     89         begin
     90             y:=op[i];op[i]:=op[j];op[j]:=y;
     91             inc(i);dec(j);
     92         end;
     93     until i>j;
     94     if i<r then sort(i,r);
     95     if l<j then sort(l,j);
     96 end;
     97 
     98 procedure ins1(var i:longint;l,r,ps:longint);
     99 var mid:longint;
    100 begin
    101     inc(tt);f[tt]:=f[i];i:=tt;
    102     inc(f[i].sum);if l=r then exit;
    103     mid:=(l+r)div 2;
    104     if ps<=mid then ins1(f[i].l,l,mid,ps) else ins1(f[i].r,mid+1,r,ps);
    105 end;
    106 
    107 procedure ins(var i:longint;l,r,ll,rr:longint);
    108 var mid:longint;
    109 begin
    110     inc(tt);f[tt]:=f[i];i:=tt;
    111     if(ll<=l)and(r<=rr)then
    112     begin
    113         inc(f[i].tag);inc(f[i].sum,r-l+1);
    114         exit;
    115     end;
    116     mid:=(l+r)div 2;
    117     if ll<=mid then ins(f[i].l,l,mid,ll,rr);
    118     if mid+1<=rr then ins(f[i].r,mid+1,r,ll,rr);
    119     f[i].sum:=f[i].tag*(r-l+1)+f[f[i].l].sum+f[f[i].r].sum;
    120 end;
    121     
    122 function ask(i,l,r,ll,rr:longint):longint;
    123 var mid,tmp:longint;
    124 begin
    125     if i=0 then exit(0);
    126     if(ll<=l)and(r<=rr)then exit(f[i].sum);
    127     tmp:=f[i].tag*(min(rr,r)-max(ll,l)+1);
    128     mid:=(l+r)div 2;
    129     if ll<=mid then tmp:=tmp+ask(f[i].l,l,mid,ll,rr);
    130     if mid+1<=rr then tmp:=tmp+ask(f[i].r,mid+1,r,ll,rr);
    131     exit(tmp);
    132 end;
    133 
    134 begin
    135     assign(input,'sf.in');reset(input);
    136     assign(output,'sf.out');rewrite(output);
    137     readln(n,m,p1,p2);
    138     for i:=1 to n do read(a[i]);
    139     for i:=1 to n do p[i]:=n-i+1;
    140     fillchar(c,sizeof(c),0);
    141     for i:=1 to n do
    142     begin
    143         op1[i].l:=askmx(p[a[i]]);op1[i].id:=i;
    144         insmx(p[a[i]],i);
    145     end;
    146     fillchar(c,sizeof(c),$3f);inf:=c[1];
    147     for i:=n downto 1 do
    148     begin
    149         op1[i].r:=askmn(p[a[i]]);
    150         insmn(p[a[i]],i);
    151     end;
    152     sort1(1,n);
    153     j:=1;while(op1[j].l=0)and(j<=n)do inc(j);
    154     fillchar(root1,sizeof(root1),0);
    155     fillchar(root2,sizeof(root2),0);
    156     for i:=1 to n do
    157     begin
    158         root1[i]:=root1[i-1];
    159         while(j<=n)and(op1[j].l<=i)do 
    160         begin
    161             if op1[j].r<inf then ins1(root1[i],1,n,op1[j].r);
    162             inc(j);
    163         end;
    164     end;
    165     tot:=0;
    166     for i:=1 to n do
    167     begin
    168         l:=op1[i].l+1;r:=op1[i].id-1;
    169         if (l<=r)and(op1[i].r<inf) then
    170         begin
    171             inc(tot);op[tot].ps:=op1[i].r;
    172             op[tot].l:=l;op[tot].r:=r;
    173         end;
    174         l:=op1[i].id+1;r:=min(n,op1[i].r-1);
    175         if (l<=r)and(op1[i].l>0) then
    176         begin
    177             inc(tot);op[tot].ps:=op1[i].l;
    178             op[tot].l:=l;op[tot].r:=r;
    179         end;
    180     end;
    181     sort(1,tot);
    182     j:=1;
    183     for i:=1 to n do
    184     begin
    185         root2[i]:=root2[i-1];
    186         while(j<=n)and(op[j].ps=i)do
    187         begin
    188             ins(root2[i],1,n,op[j].l,op[j].r);
    189             inc(j);
    190         end;
    191     end;
    192     for i:=1 to m do
    193     begin
    194         readln(l,r);
    195         ans:=int64(p1)*(ask(root1[r],1,n,l,r)-ask(root1[l-1],1,n,l,r)+(r-l));
    196         ans:=ans+int64(p2)*(ask(root2[r],1,n,l,r)-ask(root2[l-1],1,n,l,r));
    197         writeln(ans);
    198     end;
    199     close(input);close(output);
    200 end.
    View Code
  • 相关阅读:
    【洛谷 1546】最短网络
    [Algorithms]Greedy
    [Operating System]Thread Pool
    微积分——外微分形式的微积分
    Codeforce Round #548(Div2)
    Codeforce Round #544(Div3)
    Codeforce Round #545(Div2) (BCD题解)
    桶排序桶的前缀和/差分
    Codeforce Round #545(Div2)
    Codeforce Round #531(Div3)
  • 原文地址:https://www.cnblogs.com/oldjang/p/6729449.html
Copyright © 2011-2022 走看看