考題 列舉 旋轉子段 列舉 推導優化

2021-09-17 20:32:24 字數 1874 閱讀 6261

zyl有n張牌編號分別為1, 2,……,n。他把這n張牌打亂排成一排,然後他要做一次旋轉使得旋轉後固定點盡可能多。如果第i個位置的牌的編號為i,我們就稱之為固定點。旋轉可以被認為是將其中的乙個子段旋轉180度,這意味著子段的第一張牌和最後一張牌交換位置,以及第二張牌和倒數第二張牌交換位置,等等。寫乙個程式,找到旋轉子段(子段長度可以為1)。

有乙個序列,需要找到乙個子串行並對這乙個子串行進行翻轉,求a[i

]=i(

1≤i≤

)a[i]=i(1\leq i \leq)

a[i]=i

(1≤i

≤)的點的最大值。

我們首先需要找到每乙個點i的目標點a[i],顯然如果要滿足當前條件必須要旋轉[i,a[i]]或[a[i],i]的子區間。我們可以知道這乙個區間的旋轉中心就是重點i+a

[i]2

\frac

2i+a[i

]​.顯然我們可以一遍得到最原始的答案,要讓答案更加優秀,我們一定要列舉若干個旋轉中心,因此我們去每一每乙個座標作為旋轉中心,考慮以這個點為中心所旋轉的長度:使答案改變必須要旋轉,有可能旋轉一部分也有可能旋轉全部,因為在旋轉的過程中可能會使本來在正確位置上的點錯位。

因此我們列舉的長度是每乙個不同的旋轉子區間的長度且從小到大列舉,因為從小到大有利於統計區間內滿足的對數;例如我們旋轉的區間是[l,r],且這是以l+r

2\frac

2l+r

​為旋轉中心的第k個長度,那麼當前的答案為:sum

(1,l

)+su

m(r,

n)+k

,sum

(a,b

)表示區

間[a,

b]內符

合條件的

答案

.sum(1,l)+sum(r,n)+k,sum(a,b)表示區間[a,b]內符合條件的答案.

sum(1,

l)+s

um(r

,n)+

k,su

m(a,

b)表示

區間[a

,b]內

符合條件

的答案.

其中這裡的sun可以用字首和來完成。

**如下:

#include

#define pb push_back

using

namespace std;

const

int n =

200010

;int n;

int a[n]

;int pos[n]

;int sum[n]

;vector<

int>cir[n]

;inline

intsz

(int x)

inline

ints

(int l,

int r)

inline

intread

(void

)int

main

(void

)for

(int i=

1;i<=n;

++i)

cir[i+pos[i]].

pb(abs(i-pos[i])+

1);int ans = sum[n]

;for

(int i=

1;i<=

2*n;

++i)

if(i%2==

1)cnt ++

;//cnt表示以i/2為對稱中心的第幾組數

ans =

max(ans,cnt+s(

1,l-1)

+s(r+1

,n));}

} cout

}

超詳細題解 旋轉子段

題目描述 zyl有n張牌編號分別為1,2,n。他把這n張牌打亂排成一排,然後他要做一次旋轉使得旋轉後固定點盡可能多。如果第i個位置的牌的編號為i,我們就稱之為固定點。旋轉可以被認為是將其中的乙個子段旋轉180度,這意味著子段的第一張牌和最後一張牌交換位置,以及第二張牌和倒數第二張牌交換位置,等等。寫...

位段,列舉,聯合

前面我們說過了自定義型別,包含結構體,位段,列舉,聯合。前一篇我們總結了結構體,今天來說一下位段,列舉,聯合。一 位段 1 位段概念 c語言中允許在乙個結構體中以位為單位來指定其成員所佔記憶體長度,這種以位為單元的成員稱為 位段 或 位域 1 位段的成員可以是int,unsigned int,sig...

位段 列舉 聯合

2.列舉 3.聯合 1.位段的成員必須是 int,unsigned int signed 即必須是整形家族 這是因為位段的成員是以位元位為單位進行儲存的,假如是浮點型別,給成員乙個5.3的容量,0.3的位元位去 找呢?2.位段的成員名後面有乙個冒號和數字 3.具體宣告如下 1.平時我們開闢空間都是偶...