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.