POI 2011 Lollipop 二分 特判

2021-07-03 07:39:48 字數 3170 閱讀 5556

給你乙個長度為

n 的序列a[

],序列裡只包含數字1或2,

q 次詢問乙個數字

x,問序列裡是否存在乙個連續的區間[l

,r] ,使得∑r

i=la

[i]=

x ,並輸出乙個可行的區間。n,

q≤106

網上題解比較少,做法都是一樣的:即大小為

x 的區間可行時,x−

2大小的區間也是可行的,因此可以離線回答所有詢問,分奇數和偶數的

x 分開討論,先找出最大的奇數和偶數的

x以及乙個可行區間,然後倒著推x−

2,x−

4...

的可行區間

這裡我提出一種新的做法(感謝溫州中學au大爺林一諾提供的思路)。

我們對序列裡包含的1的個數不超過1和大於1分開討論:

1、1的個數小於等於1

在這個情況下,我們用特判來回答每個詢問,總的複雜度o(

q)如果1的個數為0,那麼詢問的

x 必須≤∑

a[i]

,且2|x

如果1的個數為1,若

xmod2=

∑a[i

]mod

2 ,則詢問的

x 必須≤∑

a[i]

;否則說明詢問的

x 是個偶數,必須只由2組成,看1左邊的2之和和1右邊的2之和分別是否大於等於

x(保證

x 能由1左邊的2或者1右邊的2裡找出乙個子區間湊出)

2、1的個數大於1

我們找出這個序列裡離左端點最近的1的位置lo

ne和離右端點最近的1的位置n−

rone

+1序列一定是這個樣子:

22…221??…??122…22若x

>∑a

[i]−

2(min−1)

,則表明選擇的區間必須不得不選擇lo

ne和n−

rone

+1兩邊的2,若

xmod2=

∑a[i

]mod

2 ,且x≤

sum ,則顯然找得到可行區間

其他情況下,我們可以考慮在[l

one+

1,n]

區間進行二分,以及在[1

,n−r

one]

區間進行二分找出乙個位置

t ,使得x−

1≤∑t

i=lo

ne+1

≤x,或者x−1

≤∑n−

rone

i=t≤

x ,則找得到可行區間

顯然這樣的二分做法是正確的,因為只要存在合法區間,就肯定可以通過二分,在最左邊或最右邊的1旁邊找出連續的一段和,恰好等於

x 或x−

1,如果是x−

1 的話,就把那個1補上去就成了

x (序列裡只包含1或者2,因此只要存在合法區間,二分後就得不到乙個x−

3,x−

4...

大小的區間)

ps:若∑t

i=lo

ne+1

=x,或者∑n

−ron

ei=t

=x,則答案區間就是[l

one+

1,t]

([t,n−r

one]

);若∑t

i=lo

ne+1

=x−1

,或者∑n

−ron

ei=t

=x−1

,則答案區間就是[l

one,

t]([t

,n−r

one+1])

#include 

#include

#include

#include

#include

#define maxn 2100000

using namespace std;

int n,m,a[maxn],cnt[3],sum=0; //cnt[1]=1的個數,cnt[2]=2的個數

char s[maxn];

namespace specialcheck //只有乙個1,特判

for(int i=1;i<=m;i++)

if((sum%2)==0&&(x

%2)!=(sum%2))

if((sum%2)==1&&(x

%2)==0)

}if((sum%2)==0)

//sum%2==1

if(x

%2==0)

printf("%d

%d\n",n-x/2+1,n);

}else}}

}namespace binarysearchedition //二分版

for(int i=n;i>=1;i--)

if(a[i]==1)

for(int i=1;i<=n;i++) presum[i]=presum[i-1]+a[i];

for(int t=1;t<=m;t++)

if(x>sum-2

*(min(lone,rone)-1))

continue;

}int lowerbound=lone+1,upperbound=n,ans=-1;

while(lowerbound<=upperbound)

else upperbound=mid-1;

}if(ans!=-1)

else

if(presum[ans]-presum[lone]==x-1)

}lowerbound=1,upperbound=n-rone,ans=-1;

while(lowerbound<=upperbound)

else lowerbound=mid+1;

}if(ans!=-1)

else

if(presum[n-rone]-presum[ans-1]==x-1) //!!!!!

}printf("nie\n");}}

}int main()

else

return

0;}

POI 2012 Well 二分 單調性

給你乙個長度為 n 的序列 a,每次操作可以讓其中乙個數字減1,最多能進行 m 次操作,問要使得存在某個ai 0的話,max 的最小值是多少 我們可以二分答案,此問題變為判定性問題 問要使得存在某個ai 0的話,max 是否可以小於等於mi d 我們首先要操作幾次,讓整個序列滿足 max 小於等於m...

NOIP2011 選擇客棧 二分,STL

有 n 間客棧,每間客棧按某種色調裝飾,總共 k 種,每家有最低消費 w i 兩個人打算選擇同種色調的兩家不同客棧入住,同時在他們之間要有一間客棧的 w i le p 求選擇的方案數。先將所有滿足 w i le p 的 i 標記為可用的,其它的標記為不可用的。考慮對於每乙個左端點,向右找到第乙個可用...

二分答案 NOIP 2011 聰明的質監員

題意 n n 個礦石,每個礦石都有自己的重量 wi role presentation style position relative wiw i,以及價值vi v i。接下來會進行以下四個操作 1.給定 m m 個區間 l i,ri role presentation style position...