博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[CF1539E]Game with Cards
阅读量:4184 次
发布时间:2019-05-26

本文共 4422 字,大约阅读时间需要 14 分钟。

题解

首先我们可以发现,对于加上的最后一张牌,它一定会出现在一只手中,也就是说只有一只手是未知的。

于是我们很快想到了 d p dp dp,定义 L i , j L_{i,j} Li,j表示左手是第 i i i张牌,右手是新加入的第 j j j张牌时是否可行,定义 R i , j R_{i,j} Ri,j表示表示右手是第 i i i张牌,左手是新加入的第 j j j张牌时是否可行。
容易得到 d p dp dp转移方程式,假设现在加入的是第 j j j张牌,
L i , j = [ a i ∈ [ a l j , b l j ] ∧ a j ∈ [ a r j , b r j ] ] { L i , j − 1 ( i ≠ j − 1 ) ∑ k = 1 k = j − 2 R k , j − 1 ( i = j − 1 ) } L_{i,j}=\left[a_{i}\in[al_{j},bl_{j}]\wedge a_{j}\in[ar_{j},br_{j}]\right]\left\{\begin{array}{rcl}L_{i,j-1} & (i\not =j-1) \\ \sum_{k=1}^{k=j-2}R_{k,j-1} & (i= j-1)\end{array}\right\} Li,j=[ai[alj,blj]aj[arj,brj]]{
Li,j1k=1k=j2Rk,j1(i=j1)(i=j1)}
同理,有
R i , j = [ a i ∈ [ a r j , b r j ] ∧ a j ∈ [ a l j , b l j ] ] { R i , j − 1 ( i ≠ j − 1 ) ∑ k = 1 k = j − 2 L k , j − 1 ( i = j − 1 ) } R_{i,j}=\left[a_{i}\in[ar_{j},br_{j}]\wedge a_{j}\in[al_{j},bl_{j}]\right]\left\{\begin{array}{rcl}R_{i,j-1} & (i\not =j-1) \\ \sum_{k=1}^{k=j-2}L_{k,j-1} & (i= j-1)\end{array}\right\} Ri,j=[ai[arj,brj]aj[alj,blj]]{
Ri,j1k=1k=j2Lk,j1(i=j1)(i=j1)}

但很明显,如果我们直接进行 d p dp dp的话是一定会 T T T掉的,考虑通过线段树对转移进行优化。

如果通过线段树的话我们需要从新对状态进行一下定义,改称 L i L_{i} Li为左手上的数为 i i i的情况是否存在, R i R_{i} Ri同理。
每次维护 L L L R R R状态的两棵线段树,每个节点表示这段区间是否可行。
对于每次不为 a j − 1 a_{j-1} aj1的点,我们只需要判断一下它是否在范围内,将范围外的点整体赋零即可。
而对于 a i − 1 a_{i-1} ai1,我们先看看另外一棵树上是否存在可行解,如果有的话,我们就可以从那边转移过来,也就是对这棵树进行单点修改,当然需要判断一下是否合法。

最后判断是否可行看有没有解即可,但构造一组解又该怎么办了?

我们可以记录一下在那些位置发生了 a j − 1 a_{j-1} aj1的转换,它有更新到哪里去了,再从末状态往前更新即可,这样就可以还原出来一组答案序列。
再将其输出即可。

时间复杂度 O ( n l o g   m ) O\left(nlog\,m\right) O(nlogm)

源码

#include
using namespace std;#define MAXN 200005#define lowbit(x) (x&-x)#define reg register#define mkpr make_pairtypedef long long LL;typedef unsigned long long uLL;const int INF=0x3f3f3f3f;const int mo=1e9+7;const int iv2=5e8+4;const int lim=1000000;const int jzm=2333;const int orG=3,invG=332748118;const double Pi=acos(-1.0);typedef pair
pii;template
_T Fabs(_T x){
return x<0?-x:x;}template
void read(_T &x){
_T f=1;x=0;char s=getchar(); while(s>'9'||s<'0'){
if(s=='-')f=-1;s=getchar();} while('0'<=s&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);s=getchar();} x*=f;}template
void print(_T x){
if(x<0){
x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}int gcd(int a,int b){
return !b?a:gcd(b,a%b);}int add(int x,int y){
return x+y
ai||r
r)return ;if(!rt)rt=++tot; if(l==r){ tr[rt]=1;tim[rt]=aw;return ;}int mid=l+r>>1;pushdown(rt); if(ai<=mid)insert(ch[rt][0],l,mid,ai,aw); if(ai>mid)insert(ch[rt][1],mid+1,r,ai,aw); pushup(rt); } void modify(int rt,int l,int r,int al,int ar){ if(l>r||l>ar||r
ar||!rt)return ;int mid=l+r>>1; if(al<=l&&r<=ar){ tr[rt]=0;lzy[rt]=1;return ;}pushdown(rt); if(al<=mid)modify(ch[rt][0],l,mid,al,ar); if(ar>mid)modify(ch[rt][1],mid+1,r,al,ar); pushup(rt); } bool query(int rt){ return tr[rt];} int sakura(int rt,int l,int r){ if(l==r)return tim[rt];int mid=l+r>>1;pushdown(rt); if(tr[ch[rt][0]])return sakura(ch[rt][0],l,mid); return sakura(ch[rt][1],mid+1,r); }}TL,TR;signed main(){ read(n);read(m);TL.insert(TL.root,0,m,0,0);TR.insert(TR.root,0,m,0,0); for(int i=1;i<=n;i++){ read(s[i].k);read(s[i].al);read(s[i].bl);read(s[i].ar);read(s[i].br); bool Llive=TL.query(TL.root),Rlive=TR.query(TR.root); if(Llive)ansl[i]=TL.sakura(TL.root,0,m);else ansl[i]=-1; if(Rlive)ansr[i]=TR.sakura(TR.root,0,m);else ansr[i]=-1; if(s[i].ar<=s[i].k&&s[i].k<=s[i].br){ TL.modify(TL.root,0,m,0,s[i].al-1),TL.modify(TL.root,0,m,s[i].bl+1,m); if(i>1&&s[i].al<=s[i-1].k&&s[i-1].k<=s[i].bl&&Rlive) TL.insert(TL.root,0,m,s[i-1].k,i-1),choL[i]=1; } else TL.modify(TL.root,0,m,0,m); if(s[i].al<=s[i].k&&s[i].k<=s[i].bl){ TR.modify(TR.root,0,m,0,s[i].ar-1),TR.modify(TR.root,0,m,s[i].br+1,m); if(i>1&&s[i].ar<=s[i-1].k&&s[i-1].k<=s[i].br&&Llive) TR.insert(TR.root,0,m,s[i-1].k,i-1),choR[i]=1; } else TR.modify(TR.root,0,m,0,m); } if(TL.query(TL.root)||TR.query(TR.root)){ puts("Yes");int x=0,y=0;int tot=n,lim;bool f; if(TL.query(TL.root))lim=TL.sakura(TL.root,0,m),x=s[lim].k,y=s[n].k,f=0; else lim=TR.sakura(TR.root,0,m),x=s[n].k,y=s[lim].k,f=1; while(tot){ int tmpl=(y!=s[tot-1].k||!choR[tot])?s[tot-1].k:ansl[tot]; if(f){ ans[tot]=0;if(tot>lim+1)x=s[tot-1].k;else f^=1,x=s[lim=ansl[tot]].k;} else{ ans[tot]=1;if(tot>lim+1)y=s[tot-1].k;else f^=1,y=s[lim=ansr[tot]].k;} tot--; } for(int i=1;i<=n;i++)printf("%d ",ans[i]);puts(""); } else puts("No"); return 0;}

谢谢!!!

转载地址:http://xeyoi.baihongyu.com/

你可能感兴趣的文章
在Win上提交hadoop集群的作业
查看>>
JAVA IDE IntelliJ IDEA使用简介(一)—之界面元素
查看>>
GROUP BY与COUNT用法详解
查看>>
pgadmin
查看>>
Greenplum性能调优
查看>>
gp性能管理
查看>>
linux的清屏命令
查看>>
maven打jar包
查看>>
Win10系统ie浏览器打不开网页的2种解决方法
查看>>
自己搭建一套hadoop的运行环境
查看>>
本次装的hadoop版本是hadoop1.2的版本
查看>>
跳板机SecureCRT
查看>>
namenode的log时,散仙发现有如下的警告信息
查看>>
用过eclipse直接向hadoop提交MR作业
查看>>
在执行bin/hadoop checknative 命令时
查看>>
MapReduce作业
查看>>
去连接Linux系统上的HDFS
查看>>
在eclipse中远程连接并读取数据
查看>>
处理多个类似表的txt数据
查看>>
两种hadoop集群(CDH的和Apache的))在使用过程中遇到
查看>>