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

 

posted @ 2017-04-18 19:09  OldJang  阅读(199)  评论(0编辑  收藏  举报