jzoj5236. 【NOIP2017模擬8.7A組】利普希茨

Description

在這裏插入圖片描述

Input

輸入文件名爲lipschitz.in。
第一行一個整數n。
接下來一行n個整數,描述序列A。
第三行一個數q 。
接下來q行,每行三個整數。其中第一個整數type表示操作的類型。 type=0對應修改操作, type=1對應查詢操作。

Output

輸出文件名爲lipschitz.out。
對於每個查詢,給出f(A[l…r]) 。

Sample Input

輸入1:
6
90 50 78 0 96 20
6
0 1 35
1 1 4
0 1 67
0 4 11
0 3 96
1 3 5

輸入2:
50
544 944 200 704 400 150 8 964 666 596 850 608 452 103 988 760 370 723 350 862 856 0 724 544 668 891 575 448 16 613 952 745 990 459 740 960 752 194 335 575 525 12 618 80 618 224 240 600 562 283
10
1 6 6
1 1 3
0 11 78279
0 33 42738
0 45 67270
1 1 26
1 19 24
1 37 39
1 8 13
0 7 64428

Sample Output

輸出1:
78
85

輸出2:
0
744
77683
856
558
77683

Data Constraint

對於30%的數據,n,q<=500
對於60%的數據,n,q<=5000
對於100%的數據,n,q<=100000,0<=ai,val<=10^9

題外話

大爺省選加油啊。
我這個菜逼就在圖書館當個加油的吧。

題解

啊,一道包着大數據結構的sb結論題。
本着想到一個神奇的錯誤結論能過掉的,然後就沒有然後了。
這結論也是真的妙,自己還是太菜了,沒想到。

我們可以考慮那條神奇的式子:
aiajij\lceil\frac{|a_i-a_j|}{|i-j|}\rceil
那麼我們考慮把上面這個醜陋的式子換個方式看:
那麼我們考慮把每個點都變成一個點:(i,ai)(i,a_i)
然後上面的式子不就變成了求斜率嗎?

然後畫個圖就可以發現,我們對於每三個點,其中必定有一個相鄰的點的斜率最小。

線段樹即可。

代碼

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn=100010;

int n,m,a[maxn],ans,xx,yy,ki,x,y,jia,answer,wz;
struct node{
	int ma,mi,wz1,wz2;
}tree[maxn*4];

void findmax(int x,int l,int r,int st,int en)
{
	if (l==st && r==en)
	{
		if (tree[x].ma>answer) wz=tree[x].wz1;
		answer=max(answer,tree[x].ma);
	}
	else
	{
		int mid=(l+r)/2;
		if (en<=mid) findmax(x*2,l,mid,st,en);
		else if (st>mid) findmax(x*2+1,mid+1,r,st,en);
		else
		{
			findmax(x*2,l,mid,st,mid);
			findmax(x*2+1,mid+1,r,mid+1,en);
		}
	}
}

void findmin(int x,int l,int r,int st,int en)
{
	if (l==st && r==en)
	{
		if (tree[x].mi<answer) wz=tree[x].wz2;
		answer=min(answer,tree[x].mi);
	}
	else
	{
		int mid=(l+r)/2;
		if (en<=mid) findmin(x*2,l,mid,st,en);
		else if (st>mid) findmin(x*2+1,mid+1,r,st,en);
		else
		{
			findmin(x*2,l,mid,st,mid);
			findmin(x*2+1,mid+1,r,mid+1,en);
		}
	}
}

void modify(int x,int l,int r,int st,int en)
{
	if (l==r)
	{
		tree[x].ma=en;tree[x].mi=en;
		tree[x].wz1=l;tree[x].wz2=l;
	}
	else
	{
		int mid=(l+r)/2;
		if (st<=mid) modify(x*2,l,mid,st,en);
		else modify(x*2+1,mid+1,r,st,en);
		if (tree[x*2].ma>tree[x*2+1].ma) tree[x].wz1=tree[x*2].wz1;else tree[x].wz1=tree[x*2+1].wz1;
		if (tree[x*2].mi<tree[x*2+1].mi) tree[x].wz2=tree[x*2].wz2;else tree[x].wz2=tree[x*2+1].wz2;
		tree[x].ma=max(tree[x*2].ma,tree[x*2+1].ma);
		tree[x].mi=min(tree[x*2].mi,tree[x*2+1].mi);
	}
}

__attribute__((optimize("-O3")))
int main()
{
	freopen("lipschitz.in","r",stdin);
	freopen("lipschitz.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		if (i>1)
		modify(1,1,n-1,i-1,abs(a[i]-a[i-1]));
	}
	scanf("%d",&m);
	while (m>0)
	{
		m--;
		scanf("%d%d%d",&ki,&x,&y);
		if (ki==0)
		{
			a[x]=y; 
			modify(1,1,n-1,x-1,abs(a[x]-a[x-1]));
			modify(1,1,n-1,x,abs(a[x]-a[x+1]));
		}
		else
		{
			if (x==y) printf("0\n");
			else
			{
				answer=0;
				wz=0;
				findmax(1,1,n-1,x,y-1);
				printf("%d\n",answer);
			}
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章