• CF1539E Game with Cards 题解


    Codeforces
    Luogu

    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;
    }
    
  • 相关阅读:
    Razor 视图引擎的一些属性和方法
    Asp.Net Mvc Razor
    微信小程序时代已经来临
    ionic常用命令记录
    ionic中将service中异步返回的数据赋值给controller的$scope
    nodejs连接mysql实例
    转载:ionic+nodejs开发遇到的跨域和post请求数据问题
    NodeJs-- 新建项目实例
    Bootstrap学习指南
    ios开发环境配置及cordova安装与常用命令
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15004025.html
Copyright © 2020-2023  润新知