[CSP-S Simulation Test]: F (DP + segment tree)

Topic Portal (internal title 49)


Input Format

The first n-row four integers $, Q, A, B $.
Then $ n $ lines each integer $ p_i $.


Output Format

A row of integer answer.


Sample

Sample input:

10 3 3 7

4

2

8

Sample output:

4


Data range and tips

For $ 30 \% $ data: $ n, q \ leqslant 2,000 $
For all data:
$. 1 \ n-leqslant, Q \ ^. 5 leqslant {10} $
$. 1 \ leqslant P_i \ $ leqslant n-


answer

First, we consider the $ 30 \% $ of the algorithm how to do?

$ $ Considering the DP, defined $ dp [i] [j] $ represents the first step $ I $, $ a pointer $ P_i, another pointer minimum number of steps in the $ J $.

Then we can in the state transition equation:

  $ \ Alpha.dp [i] [j] = dp [i-1] [j] + | p_i-p_ {i-1} | $ (the last time and this time a pointer is moved)

  $ \ Beta.dp [i] [p_ {i-1}] = dp [i-1] [j] + | p_i-j | $ (the last time and this time is not a movement of the pointer)

So we then consider how to optimize.

Metastatic $ \ alpha $ is actually the entire range have added $ | p_i-p_ {i-1} | $, while the transfer of $ \ beta $ we can maintain $ dp [i] [j] + j $ and $ dp [i] [j] -j $ to minimum.

So consider the tree line optimization, you can get a perfect score.

Time complexity: $ \ Theta (n \ log n) $.

Expectations score: $ 100 $ points.

Actual score: $ 100 $ points.


Code time

#include<bits/stdc++.h>
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
int n,q,a,b;
int p[100001];
long long tr[4][400001];
void pushup(int x)
{
	tr[0][x]=min(tr[0][L(x)],tr[0][R(x)]);
	tr[1][x]=min(tr[1][L(x)],tr[1][R(x)]);
	tr[2][x]=min(tr[2][L(x)],tr[2][R(x)]);
}
void pushdown(int x)
{
	if(!tr[3][x])return;
	tr[0][L(x)]+=tr[3][x];
	tr[0][R(x)]+=tr[3][x];
	tr[1][L(x)]+=tr[3][x];
	tr[1][R(x)]+=tr[3][x];
	tr[2][L(x)]+=tr[3][x];
	tr[2][R(x)]+=tr[3][x];
	tr[3][L(x)]+=tr[3][x];
	tr[3][R(x)]+=tr[3][x];
	tr[3][x]=0;
}
void build(int x,int l,int r)
{
	if(l==r)
	{
		if(l==b)
		{
			tr[0][x]=0;
			tr[1][x]=l;
			tr[2][x]=-l;
		}
		return;
	}
	int mid=(l+r)>>1;
	build(L(x),l,mid);
	build(R(x),mid+1,r);
	pushup(x);
}
void change(int x,int l,int r,int w,long long k)
{
	if(l==r)
	{
		tr[0][x]=min(tr[0][x],k);
		tr[1][x]=tr[0][x]+l;
		tr[2][x]=tr[0][x]-l;
		return;
	}
	int mid=(l+r)>>1;
	pushdown(x);
	if(w<=mid)change(L(x),l,mid,w,k);
	else change(R(x),mid+1,r,w,k);
	pushup(x);
}
long long ask1(int x,int l,int r,int L,int R)
{
	if(R<l||r<L)return 200209230020020923;
	if(L<=l&&r<=R)return tr[2][x];
	int mid=(l+r)>>1;
	pushdown(x);
	return min(ask1(L(x),l,mid,L,R),ask1(R(x),mid+1,r,L,R));
}
long long ask2(int x,int l,int r,int L,int R)
{
	if(R<l||r<L)return 200209230020020923;
	if(L<=l&&r<=R)return tr[1][x];
	int mid=(l+r)>>1;
	pushdown(x);
	return min(ask2(L(x),l,mid,L,R),ask2(R(x),mid+1,r,L,R));
}
int main()
{
	scanf("%d%d%d%d",&n,&q,&a,&b);
	memset(tr[0],0x3f,sizeof(tr[0]));
	memset(tr[1],0x3f,sizeof(tr[1]));
	memset(tr[2],0x3f,sizeof(tr[2]));
	build(1,1,n);
	for(int i=1;i<=q;i++)
	{
		scanf("%d",&b);
		tr[0][0]=min(ask1(1,1,n,1,b)+b,ask2(1,1,n,b,n)-b);
		tr[0][1]+=abs(a-b);
		tr[1][1]+=abs(a-b);
		tr[2][1]+=abs(a-b);
		tr[3][1]+=abs(a-b);
		change(1,1,n,a,tr[0][0]);
		a=b;
	}
	cout<<tr[0][1]<<endl;
	return 0;
}

rp ++

Guess you like

Origin www.cnblogs.com/wzc521/p/11563922.html