1. 程式人生 > 其它 >CF1539E Game with Cards 題解

CF1539E Game with Cards 題解

P.S.

補 VP 題。

Description.

卡老師手上拿著兩份程式碼,都有一個分數值。
剛開始卡老師一分都不會,所以兩份程式碼的分數值都是 \(0\)
每次老K會給卡老師一份程式碼,卡老師必須且只能把他的一份程式碼卡成老K給的。
不過每次卡老師為了不被發現,所以每卡完一次都必須保證第一份程式碼的分數在 \([L_{i,0},R_{i,0}]\) 之間,第二份在 \([L_{i,1},R_{i,1}]\) 之間。
問卡老師能不能卡到最後。

Solution.

首先,我們考慮把他當做一段 \(0,1\) 串。
然後,模擬一下,我們會發現。

   a  ?
c1 a  c1  1
c2 c2 c1  0
c3 c3 c1  0
...
ck ck c1  0

如果有一段極長 \(0\) 串是合法的,當且僅當如下兩個條件同時滿足。

\[\forall i\in[l,r],L_{i,0}\le c_i\le R_{i,0} \]\[\forall i\in[l,r],L_{i,1}\le c_{l-1}\le R_{i,1} \]

極長 \(1\) 同理。
我們觀察式子發現,如果從前往後推,其中的 \(C_{l-1}\) 不同會導致不具有單調性。
但是從後往前推我們只需要記錄 \(\max\{L_{i-1,?}\}\)\(\min\{R_{i-1,?}\}\) 然後就可以 \(O(1)\) 判斷當前是否可行(對於條件 2。
所以我們從後往前,這樣對於一個轉移點,必定是它後面的一段相鄰區間可以轉移到它。
這樣就具有單調性了,可以優化了。
我們維護 \(0\)

\(1\) 分別的最後可行端點,檢查能否轉移到當前位置。
然後就可以直接 \(O(n)\) 掃一遍的複雜度內 AC 此題。

Coding.

點選檢視程式碼
//是啊,你就是那隻鬼了,所以被你碰到以後,就輪到我變成鬼了{{{
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),f=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	f?x=-x:x;
}/*}}}*/
const int N=100005;int n,m,l[N][2],r[N][2],c[N],nx[N][2];
int main()
{
	//以下程式碼中,wh 表示最靠前的可行位置,nw 表示當前第一個條件能否滿足
 	//ck 表示當前能否滿足兩個條件,L,R 分別表示當前最大左界和最小右界
	read(n),read(m);int wh[2]={n+1,n+1};for(int i=1;i<=n;i++)
		read(c[i]),read(l[i][0]),read(r[i][0]),read(l[i][1]),read(r[i][1]);
	int nw[2]={1,1},ck[2]={0,0},L[2]={0,0},R[2]={m,m};for(int i=n;i;i--)
	{
		nw[0]&=l[i][0]<=c[i]&&c[i]<=r[i][0],nw[1]&=l[i][1]<=c[i]&&c[i]<=r[i][1];
		L[0]=max(L[0],l[i][1]),R[0]=min(R[0],r[i][1]),L[1]=max(L[1],l[i][0]),R[1]=min(R[1],r[i][0]);
		ck[0]=nw[0]&&(L[0]<=c[i-1]&&c[i-1]<=R[0]),ck[1]=nw[1]&&(L[1]<=c[i-1]&&c[i-1]<=R[1]);
		(ck[0]?nx[i][0]=wh[0]:0),(ck[1]?nx[i][1]=wh[1]:0);
		if(ck[0]) nw[1]=1,wh[1]=i,L[1]=0,R[1]=m;
		if(ck[1]) nw[0]=1,wh[0]=i,L[0]=0,R[0]=m;
	}
	if(wh[0]>1&&wh[1]>1) return puts("No"),0;else puts("Yes");
	for(int i=1,p=wh[1]>1;i<=n;i=nx[i][p],p^=1) for(int j=i;j<nx[i][p];j++) printf("%c ",'0'|p);
	return putchar('\n'),0;
}