P11080 [ROI 2019 Day 1] 拍照 题解

news/2024/10/23 11:21:26

题意

给定 \(m\) 个位置和 \(n\) 个颜色,以及一个目标序列。找到一组合法的操作使得一个无色序列能变成目标序列。

  • 操作:选定一个颜色 \(c\) 和一个区间 \(l,r\),将 \(l,r\) 中的每个元素染色为 \(c\)。每个颜色只能用一次,且会覆盖原来的颜色。

思路

首先我们肯定是对一组颜色的左端点到右端点的位置进行染色,这点我们借助图来理解。

在上图中,两条染色区间相交,黑色区间把红色区间的一部分给覆盖了,也就是中间的那一段。而此时红色染右边的一个区间和染右、中两个区间没有区别,所以我们为了简便,只记最后染完(被覆盖后)的左端点与右端点。

在上图中,黑色区间包含了红色区间,如果黑色区间先染,则红色区间会把黑色区间分为两部分,用因为这两部分必须一起染,所以还是染左端点与右端点之间的区间。

无解

在上面的操作中我们已经得到了一个操作序列,但目标序列可能无解,而我们的操作后的序列是有解(可行)的,此时就要输出 -1。那我们怎么判断呢?很暴力简单,用线段树模拟一遍操作序列,最后在比对目标序列与操作后的序列即可。

Code

#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int N=3e5+5;
int m,n,ans,tot;
int l[N],r[N],a[N],f[N];
struct node{int c,l,r;
}Ans[N];
int tree[N*4];
int tag[N*4];
void push_down(int p)
{if(tag[p]){tag[p<<1]+=tag[p];tag[p<<1|1]+=tag[p];tree[p<<1]+=tag[p];tree[p<<1|1]+=tag[p];tag[p]=0;}return ;
}
void push_up(int p)
{tree[p]=tree[p<<1]+tree[p<<1|1];}
void update(int p,int l,int r,int ll,int rr,int v)
{if(ll<=l&&r<=rr){tree[p]=(r-l+1)*v;tag[p]=v;return ;}push_down(p);int mid=(l+r)>>1;if(ll<=mid)update(p<<1,l,mid,ll,rr,v);if(rr>mid)update(p<<1|1,mid+1,r,ll,rr,v);push_up(p);return ;
}
int get(int p,int l,int r,int to)
{if(to==l&&to==r)return tree[p];int mid=(l+r)>>1;push_down(p);if(to<=mid)return get(p<<1,l,mid,to);else return get(p<<1|1,mid+1,r,to);
}
bool check()
{for(int i=1;i<=tot;i++)update(1,1,m,Ans[i].l,Ans[i].r,Ans[i].c);for(int i=1;i<=m;i++){int now=get(1,1,m,i);if(now!=a[i])return false;}return true;
}
signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>m>>n;for(int i=1;i<=m;i++){cin>>a[i];if(!l[a[i]])l[a[i]]=i,r[a[i]]=i;else r[a[i]]=i;}int ll,rr;ll=rr=0;for(int i=1;i<=m;i++)if(l[a[i]]==i){if(l[a[i]]>rr)ll=l[a[i]],rr=r[a[i]];else if(r[a[i]]>rr)return cout<<-1,0;Ans[++tot]=(node){a[i],l[a[i]],r[a[i]]};}if(!check())return cout<<-1,0;cout<<tot;for(int i=1;i<=tot;i++)cout<<"\n"<<Ans[i].c<<" "<<Ans[i].l<<" "<<Ans[i].r;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/72115.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

CSP2024-38

2A 题意:定义 \(S(n, k)\) 为 \(n\) 在 \(k\) 进制下的数位和。 给定 \(n, k, x\),求 \(\sum_{i = 2}^k[S(n, i) \le x]\)。\(n \le 10^{12},\ k, x \le 10^{18}\)。\(i \le \sqrt n\),直接枚举。\(i > \sqrt n\),最多两位数,总和等于 \(\lfloor\dfrac{n}{i}\rfloor + …

VMware vSAN 8.0U3b - 存储虚拟化软件

VMware vSAN 8.0U3b - 存储虚拟化软件VMware vSAN 8.0U3b - 存储虚拟化软件 vSAN 8 with Express Storage Architecture 请访问原文链接:https://sysin.org/blog/vmware-vsan/ 查看最新版。原创作品,转载请保留出处。 作者主页:sysin.orgVMware vSAN 存储虚拟化软件 vSAN 利…

dotnet DirectX 做一个简单绘制折线笔迹的 D2D 应用

本文将告诉大家如何从简单的控制台开始,使用 Vortice 辅助调用 Direct2D1 的功能,配合 WM_Pointer 消息,制作一个简单绘制触摸折线笔迹的 D2D 应用前置博客: dotnet DirectX 通过 Vortice 控制台使用 ID2D1DeviceContext 绘制画面 本文属于 D2D 系列博客,更多 D2D 相关博客…

记 X11 里面触摸的一些行为

这是我在学习 CPF 和 Avalonia 过程中,编写的 X11 触摸测试程序所测试到的一些行为前置博客: dotnet 学习 CPF 框架笔记 了解 X11 里如何获取触摸信息 X11 触摸测试程序 测试程序开源代码路径: https://github.com/dotnet-campus/ManipulationDemo/tree/master/Manipulation…

怎么利用 OBS 推送 webrtc 流 ( whip/whep ) 到 smart rtmpd

webrtc whip 推流 & whep 拉流简介 RFC 定义 通用的 webrtc 对于 SDP 协议的交换已经有对应的 RFC 草案出炉了。这就是 WHIP( push stream ) & WHEP ( pull stream ) . WHIP RFC Link: https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html WHEP RFC Link: h…

关于蜂窝模组天线的一些大白话常识

​ 蜂窝模组这个产品形态存在的最大意义,从产业链分工上来说,是提升社会效率。 毕竟让每个需要蜂窝通信的公司自建一个团队重复造轮子,既不经济,也不聪明,就像做衣服的绝大部份公司也没必要自己做拉链一样。 蜂窝模组产品本身最大的特点之一——就是标准化。 无论软件的标…

AT开发HTTP应用:Air780EP低功耗4G模组

​已经写了一篇基于Air780EP模组AT开发的FOTA远程升级指南,有客户朋友询问能否讲讲HTTP应用部分?本期特别安排——涵盖HTTP基本应用流程、GET/POST/SSL请求示例、断点续传、常见问题等内容。 Air780EP是一款低功耗4G全网通模组,兼容模组行业1618经典封装,支持OpenCPU开发及…