bzoj4444 Scoi2015 國旗計畫

2021-08-19 04:47:49 字數 1493 閱讀 9973

題目傳送門

好題解法:

因為區間互不包含。

那麼左端點在區間內最右邊的的區間一定是當前區間能擴充套件到最遠的區間。

這句話有點繞。舉個例子。

假設當前區間為1~5。

那麼我們往右擴充套件。

找到左端點最右且小於等於5的區間。

這個區間一定是最優解。

因為區間互不包含啊。如果這個區間不是最優解的話那麼就被別的包含了。。

因為題目是環。需要轉化成鏈。

所以把環複製乙份放在後面就變成了鏈了。

如果當前區間起點為l。整個環長度為mx。

那麼我們需要覆蓋l到l+mx

然後我們把這個區間能擴充套件到的最右端看做乙個父子關係。

從l到l+mx這個過程我們可以看做找到乙個祖先是大於等於l+mx的。

這個過程倍增實現就行。

然後通過貪心可以發現每個區間參與的答案相差都不超過1的。

那麼我們求出第乙個區間參與的答案。

以後的答案我們分別用前面的答案-1,0,+1來驗證即可

**實現:

#include

#include

#include

#include

#include

#include

#include

using namespace std;

int l[210000],r[210000],l[210000],r[210000],a[410000];

bool cmp(int a,int b) else l=mid+1;

}return ans;

}struct node s[410000];int mx[21][1100000],bin[21];

bool cmp1(node n1,node n2)

int main()

sort(a+1,a+1+len,cmp);int mmax=0;

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

len=0;

for(int i=1;i<=n;i++) sort(s+1,s+1+len,cmp1);

int t=1,f=0;memset(mx,0,sizeof(mx));

for(int i=1;i<=2

*mmax;i++)

mx[0][i]=f;

}bin[0]=1;for(int i=1;i<=20;i++)bin[i]=bin[i-1]*2;

for(int j=1;j<=20;j++)for(int i=1;i<=2

*mmax;i++)mx[j][i]=mx[j-1][mx[j-1][i]];

int ans;

for(ans=0;ansif(jump(r[1],ans)>=l[1]+mmax) break;

printf("%d",ans+1);

for(int i=2;i<=n;i++)

return

0;}

bzoj 4444 Scoi2015 國旗計畫

破環成鏈,對於每個點的策略是找最後乙個能傳遞到的旗手,每個點都指向乙個特定的點,這樣形成了一棵樹。如果father x 傳遞到的最後乙個點是y,那麼x傳遞到的最後乙個點在x到y的路徑上,所以如果把一條鏈看成一段決策,那麼決策點所在的深度是不減的。所以可以對樹進行dfs,維護乙個雙端佇列,每次暴力進出...

BZOJ4444 Scoi2015 國旗計畫

首先將座標離散化,因為區間互不包含,可以理解為對於每個起點輸出最少需要多少個戰士。將環倍長,破環成鏈,設 f i 表示區間左端點不超過 i 時右端點的最大值,可以通過 o n 遞推求出。那麼如果將 f i 看成 i 的祖先的話,它實際上形成了一棵以 2n 為根的樹。首先暴力計算出1號點的答案 t 設...

4444 Scoi2015 國旗計畫

time limit 20 sec memory limit 256 mb submit 246 solved 111 submit status discuss a國正在開展一項偉大的計畫 國旗計畫。這項計畫的內容是邊防戰士手舉國旗環繞邊境線奔襲一圈。這 項計畫需要多名邊防戰士以接力的形式共同完成...