【ZJOI2017 Round2练习&BZOJ4826】D1T2 sf(主席树,单调栈)

题意:

思路:From http://blog.csdn.net/neither_nor/article/details/70211150

对每个点i,单调栈求出左边和右边第一个大于i的位置,记为l[i]和r[i]

那么(l[i],r[i])会产生p1的贡献

左端点为l[i],右端点在[i+1,r-1]的点对都会产生p1的贡献

右端点为r[i],左端点在[l+1,i-1]的点对都会产生p2的贡献

将点对看成平面上的点,横坐标左端点纵坐标右端点,上述贡献分别对应单点加和线段加

查询就是矩形求和

From MG:

考虑修改均为如(x,y1..y2)与(x1..x2,y)形式

因为询问均为矩形,则修改(y1..y2,x)与(x,y1..y2)等价

若统一转化为(x,y1..y2)形式,可用主席树维护

若统一转化为(y1..y2,x)形式,可用树状数组套主席树维护

注意点对(i,i)都有p1的贡献

  1 var t:array[0..10000000]of record
  2                            a,s:int64;
  3                            l,r:longint;
  4                           end;
  5     d:array[1..1000000,1..4]of longint;
  6     l,r:array[1..300000]of longint;
  7     root,stk,a:array[0..300000]of longint;
  8     n,m,i,cnt,j,top,que,x,y,p1,p2:longint;
  9     ans:int64;
 10 
 11 procedure update(l,r,x,y,v:longint;var p:longint);
 12 var mid:longint;
 13 begin
 14  if (l>x)or(x>y) then exit;
 15  inc(cnt); t[cnt]:=t[p]; p:=cnt;
 16  t[p].s:=t[p].s+int64(v)*(y-x+1);
 17  if (l=x)and(r=y) then
 18  begin
 19   t[p].a:=t[p].a+v;
 20   exit;
 21  end;
 22  mid:=(l+r)>>1;
 23  if y<=mid then update(l,mid,x,y,v,t[p].l)
 24   else if x>mid then update(mid+1,r,x,y,v,t[p].r)
 25   else
 26   begin
 27    update(l,mid,x,mid,v,t[p].l);
 28    update(mid+1,r,mid+1,y,v,t[p].r);
 29   end;
 30 end;
 31 
 32 procedure query(l,r,x,y,p1,p2:longint);
 33 var mid:longint;
 34 begin
 35  if (l=x)and(r=y) then
 36  begin
 37   ans:=ans+t[p1].s-t[p2].s;
 38   exit;
 39  end;
 40  ans:=ans+(t[p1].a-t[p2].a)*(y-x+1);
 41  mid:=(l+r)>>1;
 42  if y<=mid then query(l,mid,x,y,t[p1].l,t[p2].l)
 43   else if x>mid then query(mid+1,r,x,y,t[p1].r,t[p2].r)
 44   else
 45   begin
 46    query(l,mid,x,mid,t[p1].l,t[p2].l);
 47    query(mid+1,r,mid+1,y,t[p1].r,t[p2].r);
 48   end;
 49 end;
 50 
 51 procedure swap(var x,y:longint);
 52 var t:longint;
 53 begin
 54  t:=x; x:=y; y:=t;
 55 end;
 56 
 57 procedure qsort(l,r:longint);
 58 var i,j,mid:longint;
 59 begin
 60  i:=l; j:=r; mid:=d[(l+r)>>1,1];
 61  repeat
 62   while mid>d[i,1] do inc(i);
 63   while mid<d[j,1] do dec(j);
 64   if i<=j then
 65   begin
 66    swap(d[i,1],d[j,1]);
 67    swap(d[i,2],d[j,2]);
 68    swap(d[i,3],d[j,3]);
 69    swap(d[i,4],d[j,4]);
 70    inc(i); dec(j);
 71   end;
 72  until i>j;
 73  if l<j then qsort(l,j);
 74  if i<r then qsort(i,r);
 75 end;
 76 
 77 begin
 78  assign(input,'bzoj4826.in'); reset(input);
 79  assign(output,'bzoj4826.out'); rewrite(output);
 80  readln(n,que,p1,p2);
 81  for i:=1 to n do read(a[i]);
 82  top:=1; stk[top]:=0; a[0]:=maxlongint;
 83  for i:=1 to n do
 84  begin
 85   while (top>0)and(a[i]>a[stk[top]]) do dec(top);
 86   if top=1 then l[i]:=0
 87    else l[i]:=stk[top];
 88   inc(top); stk[top]:=i;
 89  end;
 90  top:=1; stk[top]:=n+1; a[n+1]:=maxlongint;
 91  for i:=n downto 1 do
 92  begin
 93   while (top>0)and(a[i]>a[stk[top]]) do dec(top);
 94   if top=1 then r[i]:=n+1
 95    else r[i]:=stk[top];
 96   inc(top); stk[top]:=i;
 97  end;
 98  for i:=1 to n do
 99  begin
100   if (l[i]>0)and(r[i]<=n) then
101   begin
102    inc(m); d[m,1]:=l[i]; d[m,2]:=r[i]; d[m,3]:=r[i]; d[m,4]:=p1;
103   end;
104   if l[i]>0 then
105   begin
106    inc(m); d[m,1]:=l[i]; d[m,2]:=i+1; d[m,3]:=r[i]-1; d[m,4]:=p2;
107   end;
108   if r[i]<=n then
109   begin
110    inc(m); d[m,1]:=r[i]; d[m,2]:=l[i]+1; d[m,3]:=i-1; d[m,4]:=p2;
111   end;
112  end;
113  qsort(1,m);
114  j:=1;
115  for i:=1 to n do
116  begin
117   root[i]:=root[i-1];
118   while (j<=m)and(d[j,1]=i) do
119   begin
120    update(1,n,d[j,2],d[j,3],d[j,4],root[i]);
121    inc(j);
122   end;
123  end;
124  for i:=1 to que do
125  begin
126   readln(x,y);
127   ans:=(y-x)*p1;
128   query(1,n,x,y,root[y],root[x-1]);
129   writeln(ans);
130  end;
131  close(input);
132  close(output);
133 end.

 

posted on 2017-04-19 10:10  myx12345  阅读(148)  评论(0编辑  收藏  举报

导航