Description
Input
Output
Sample Input
4 4
1 2 5 6
1 2 4 2
1 1 2
1 3 4
1 1 4
1 1 3
Sample Output
1
2
8
6
Data Constraint
Solution
这题一开始时以为是数据结构,但是想了很久都没什么想法,结果原来是链表暴力跳!!!
做这题充分利用数据随机这个重要条件!
记 l[i],r[i] l [ i ] , r [ i ] 分别表示点 i i 向左向右看比自己高的位置在哪儿。
这个可以预处理出来,比如说算 ,就可以用个指针 j=i−1 j = i − 1 ,不断比, j=l[j] j = l [ j ]
不断跳以找到符合条件的 j j ,再 。
由于数据随机,跳的次数约为 log l o g 次 ,故预处理的复杂度为 O(N log N) O ( N l o g N ) 。
接着我们来处理修改,显然修改横坐标是没用的,直接数组赋值就好了。
而改高度的话,就可能会变动一些 l,r l , r ,我们考虑暴力维护。
现用上述方法重新求出修改点 x x 的 。
比如说我们要重新维护一些点的 r r ,那么显然只有第 到 x−1 x − 1 个点需要暴力修改。
那还等什么,暴力改呗!由于数据随机,修改的复杂度约为 O(log N) O ( l o g N ) 或 O(log2N) O ( l o g 2 N ) 。
而改 l l 也同理,就是从 到 r[x] r [ x ] 要暴力修改。
最后就是最重要的询问了。
我们可以利用单调性来解决问题!
设区间为 [x,y] [ x , y ] ,那么当沿着 x x 的 和 y y 的 一直跳,
那么跳出来的点高度一定是先单调上升、再单调下降的。
那么贪心一下,令 l1,r1 l 1 , r 1 分别沿着单调上升、单调下降的点跳,
先保证 l1 l 1 的高度不比 r1 r 1 高,扫一遍更新答案。
之后再使保证 r1 r 1 的高度不比 l1 l 1 高,再扫一遍更新答案。
由于数据随机,这些点的数量约为 log 个 ,故查询的复杂度约为 O(log N) O ( l o g N ) 。
那么总时间复杂度就约为 O(N log N) O ( N l o g N ) ,竟轻松通过本题!!!
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
typedef long long LL;
const int N=5e5+5;
struct data
{
int x,y;
}a[N];
int l[N],r[N];
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
inline LL max(LL x,LL y)
{
return x>y?x:y;
}
int main()
{
freopen("board.in","r",stdin);
freopen("board.out","w",stdout);
int n=read(),q=read();
for(int i=1;i<=n;i++) a[i].x=read();
for(int i=1;i<=n;i++) a[i].y=read();
for(int i=1;i<=n;i++)
{
int pos=i-1;
while(pos && a[pos].y<=a[i].y) pos=l[pos];
l[i]=pos;
}
for(int i=n;i;i--)
{
int pos=i+1;
while(pos<=n && a[pos].y<=a[i].y) pos=r[pos];
r[i]=pos;
}
while(q--)
{
int ty=read(),x=read(),y=read();
if(ty==3) a[x].x=y; else
if(ty==2)
{
a[x].y=y;
int pos=x-1;
while(pos && a[pos].y<=a[x].y) pos=l[pos];
l[x]=pos;
pos=x+1;
while(pos<=n && a[pos].y<=a[x].y) pos=r[pos];
r[x]=pos;
for(int i=x-1;i>=l[x];i--)
{
pos=i+1;
while(pos<=n && a[pos].y<=a[i].y) pos=r[pos];
r[i]=pos;
}
for(int i=x+1;i<=r[x];i++)
{
pos=i-1;
while(pos && a[pos].y<=a[i].y) pos=l[pos];
l[i]=pos;
}
}else
{
LL ans=0;
for(int i=x,j=y;i<=y;i=r[i])
{
while(j>i && a[i].y>a[j].y) j=l[j];
if(j<=i) break;
ans=max(ans,(LL)(a[j].x-a[i].x)*a[i].y);
}
for(int i=y,j=x;i>=x;i=l[i])
{
while(j<i && a[i].y>a[j].y) j=r[j];
if(j>=i) break;
ans=max(ans,(LL)(a[i].x-a[j].x)*a[i].y);
}
printf("%lld\n",ans);
}
}
return 0;
}