zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    微人事项目-mybatis-持久层
    通过外键连接多个表
    springioc
    Redis 消息中间件 ServiceStack.Redis 轻量级
    深度数据对接 链接服务器 数据传输
    sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取
    sqlserver 索引优化 CPU占用过高 执行分析 服务器检查
    sql server 远程备份 bak 删除
    冒泡排序
    多线程 异步 beginInvoke EndInvoke 使用
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15004025.html
Copyright © 2011-2022 走看看