当前位置: 首页 > news >正文

P11024 做题报告

前言

调代码要笑着调
联考题目放在 T3 其实不然
NOIp 放个T2差不多了
具有多个常见的经典 trick,还是有点落实价值的

题意

给出长度为 \(n\) 的数组的终止状态,总共 \(m\) 次操作,每一次将区间 \([l,r]\) 的所有数字覆盖改为 \(c\),找到一个决策顺序,要求按照这个顺序做能正好完成所有操作并且终止状态正确,或报告无解

思路

首先肯定看见覆盖问题就会尝试将其转化,一个很板子的转化就是将操作序列倒转变成每一次修改后不会再动了,类似于 白雪皑皑 的做法,然后发现有一个很显然的贪心,那就是每一次找到一个区间内要不就是被染过色了,要不就是和现在需要染色的颜色相同的区间,将其染色,因为显然这个位置如果已经合法了,就一定不会在某一个后续时刻不合法,而我们每一次染完一个区间之后都有可能会出现新的可以染的区间,并且所有区间的染色顺序不分先后,这样我们就出了一个 \(O(nm\log_2 n) ~ O(n^2m)\) 的做法,下限可以使用线段树精细维护最大最小值达到。

很显然这不是正解,发现我们做法中有一个思想,叫做每一次染色之后都有可能存在新的区间可以染色,稍加思考发现很像拓扑,但是我们不能让询问区间向询问区间连边,因为它们之间不存在包含关系,所以存在的最朴素的做法就是对于每一个节点挂在所有在这个区间里面的节点上,然后就可以跑拓扑了。

很显然这个时间复杂度依旧会超时,发现我们是将每一个在这个区间内的点挂上这个区间,所以可以使用线段树把这个节点挂上去,每一次修改就是 \(O(\log n)\) 的,而且对于每一个线段树上的节点只会更新一次,每一个询问区间可以拉成 \(\log n\) 个节点,而且每一个节点可以使用并查集维护是否被修改过,所以均摊时间复杂度是 \(O((N+M)\log_2 N)\) 的。

做法

将每一个询问区间放到线段树上,然后类似拓扑将可以直接染色的点放在队里里面,每一次取出队头然后将队头的区间的所有点都染色,使用并查集维护所有没有被染色的节点。对于每一次修改,找到这个节点在线段树上的所有祖先然后将他们修改用类似拓扑排序的方式把可以被压队的放到队内,然后如果到最后有位置没有被染色或者有操作没有使用就无解,否则将拓扑序反转就是解

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<climits>
#include<stdio.h>
#include<vector>
#include<cmath>
#include<queue>
#pragma GCC optimize(3,"Ofast","inline")
#define ll long longusing namespace std;
namespace ZYQIO{const int L=1<<20;inline char gc(){static char buf[L],*l=buf,*r=buf;if(l==r)r=(l=buf)+fread(buf,1,L,stdin);return (l==r)?EOF:*l++;}char obuf[L],*p=obuf;inline void pc(char c){if(p==obuf+L)fwrite(obuf,1,L,stdout),p=obuf;*p++=c;}inline void flush(){fwrite(obuf,1,p-obuf,stdout);}struct Reader{template<typename T>inline Reader& operator>>(T& x){x=0;short f=1;char c=gc();while(!isdigit(c)){if(c=='-')f=-1;c=gc();}while(isdigit(c))x=10*x+(c-'0'),c=gc();x*=f;return *this;}Reader(){}}cin;struct Writer{template<typename T>inline Writer& operator<<(T x){if(x < 0)pc('-'),x=-x;static short tp=0,s[40];do s[++tp]=x%10,x/=10;while(x);while(tp)pc(s[tp--] + '0');return *this;}inline Writer& operator<<(const char* s){int i=0;while(s[i])pc(s[i++]);return *this;}inline Writer& operator<<(char c){pc(c);return *this;}Writer(){}~Writer(){flush();}}cout;
}#define cin ZYQIO::cin
#define cout ZYQIO::cout
#define P pair<int,int>
#define fi first
#define se secondqueue<int>topo;const int N=5e5+9;
int n,m,d[N],a[N],vis[N];
int ql[N],qr[N],qc[N];struct node{int lt,rt;int cnt,col;vector<P>que;
};
struct SGT{#define lson(x) (x<<1)#define rson(x) (x<<1|1)node tr[N<<2];inline void pushup(int id){if(tr[lson(id)].cnt>=2 || tr[rson(id)].cnt>=2 || (tr[lson(id)].cnt==1 && tr[rson(id)].cnt==1 && tr[lson(id)].col!=tr[rson(id)].col))return tr[id].cnt=2,tr[id].col=0,void();if(tr[lson(id)].cnt==1) return tr[id].cnt=1,tr[id].col=tr[lson(id)].col,void();if(tr[rson(id)].cnt==1) return tr[id].cnt=1,tr[id].col=tr[rson(id)].col,void();tr[id].col=0;tr[id].cnt=0;return void();}inline void build(int id,int l,int r){tr[id].lt=l;tr[id].rt=r;if(l==r)return tr[id].cnt=1,tr[id].col=a[l],void();int mid=l+r>>1;build(lson(id),l,mid);build(rson(id),mid+1,r);pushup(id);}inline void change_add(int id,int l,int r,int num){if(tr[id].lt>=l && tr[id].rt<=r){tr[id].que.push_back({num,0});d[num]++;return void();}int mid=tr[id].lt+tr[id].rt>>1;if(l<=mid) change_add(lson(id),l,r,num);if(mid<r) change_add(rson(id),l,r,num);}inline void topo_push(int id){if(tr[id].cnt==0){for(auto &i:tr[id].que){if(i.se==0){--d[i.fi];i.se=1;if(!vis[i.fi] && d[i.fi]==0){topo.push(i.fi);vis[i.fi]=1;}}}}if(tr[id].cnt==1){for(auto &i:tr[id].que){if(i.se==0 && qc[i.fi]==tr[id].col){--d[i.fi];i.se=1;if(!vis[i.fi] && d[i.fi]==0){topo.push(i.fi);vis[i.fi]=1;}}}}}inline void change_del(int id,int pos){if(tr[id].lt==tr[id].rt){tr[id].col=0;tr[id].cnt=0;topo_push(id);return void();}int mid=tr[id].lt+tr[id].rt>>1;if(pos<=mid) change_del(lson(id),pos);else change_del(rson(id),pos);pushup(id);topo_push(id);}inline void topo_init(int id){topo_push(id);if(tr[id].lt==tr[id].rt) return void();topo_init(lson(id));topo_init(rson(id));}
}seg;int fa[N];
inline int Find(int x){return fa[x]==x?x:fa[x]=Find(fa[x]);}
vector<int>ans;int main(){cin>>n>>m;for(int i=1;i<=m;i++)cin>>ql[i]>>qr[i]>>qc[i];for(int i=1;i<=n;i++){cin>>a[i];if(a[i]==0)a[i]=-1;}seg.build(1,1,n);for(int i=1;i<=m;i++)seg.change_add(1,ql[i],qr[i],i);for(int i=1;i<=n;i++)fa[i]=i;seg.topo_init(1);for(int i=1;i<=(n<<2);i++){if(seg.tr[i].lt){if(seg.tr[i].cnt==0){for(auto &j:seg.tr[i].que){if(j.se==0){--d[j.fi];j.se=1;if(!vis[j.fi] && d[j.fi]==0){topo.push(j.fi);vis[j.fi]=1;}}}}if(seg.tr[i].cnt==1){for(auto &j:seg.tr[i].que){if(j.se==0 && qc[j.fi]==seg.tr[i].col){--d[j.fi];j.se=1;if(!vis[j.fi] && d[j.fi]==0){topo.push(j.fi);vis[j.fi]=1;}}}}}}while(topo.size()){int now=topo.front();topo.pop();ans.push_back(now);for(int i=Find(qr[now]);i>=ql[now];i=Find(i-1)){seg.change_del(1,i);fa[i]=i-1;}}if(ans.size()!=m || (seg.tr[1].cnt!=0 && seg.tr[1].col!=-1)) return cout<<"NE",0;reverse(ans.begin(),ans.end());cout<<"DA\n";for(auto i:ans)cout<<i<<' ';return 0;
}
http://www.hskmm.com/?act=detail&tid=36526

相关文章:

  • 多模态数据湖技术深化,Data Agent新能力发布!“认知”将决定企业上限
  • 2025年10月投资纠纷律师推荐:五强榜单对比评测与选择指南
  • Web刷题篇-1 [BJDCTF2020]Easy MD5
  • 云斗 YDR Special# 004 S 模拟赛
  • Berry.Live:开箱即用的.NET直播流媒体服务器
  • 2025年10月上海ICL医生推荐榜:王晓瑛领衔五强对比
  • doris集成vertica 数据源catalog
  • JUnit 6.0.0发布:Java 17基线、取消API与Kotlin协程支持
  • 详细介绍:老题新解|合法C标识符
  • 2025年10月消泡剂厂家推荐:权威榜单一网打尽
  • 国产化Excel开发组件Spire.XLS教程:使用Python将TXT文件转换为CSV
  • VMware Holodeck 9.0.1.0 发布 - 自动化部署 VCF 实验环境
  • [题解]meal
  • CADSoftTools发布两款重要更新:CAD VCL Multiplatform 16.2 与 CAD .NET 16全新发布
  • linux常用命令 - 实践
  • 2025年10月河道防撞护栏厂家全景解析报告,基于专业测评的技术、性能及市场优势深度分析
  • 在 Linux 系统上安装 Miniconda、安装 Xinference,并设置 Xinference 开机自启动
  • 作业三(结对编程)-小学四则运算题目生成与判卷(Python + 可视化)
  • 无穷小比较、等价无穷小替换
  • 【项目复现上新】Karpathy大神开源GitHub高分项目NanoChat!仅用100美元+8000行代码手搓ChatGPT
  • CF2159E
  • 2025年10月景区钢丝绳护栏厂家全景解析报告,基于专业测评的技术、性能及市场优势深度分析
  • 技术 | 在单台电脑上管理多个 GitHub 账户并解决推送问题(测试中)
  • Stable Diffusion启动提示端口错误处理
  • 阿里云API网关日志问题
  • 2025年10月半封闭滑轨丝杆模组厂家全景解析报告,基于专业测评的技术、性能及市场优势深度分析
  • ipad协议对个人微信机器人进行二次开发
  • 西安交通大学国家级医学公关交叉平台实验室建设实拍图
  • 小程序-定义头部导航
  • 2025年10月简易丝杆模组定制厂家全景解析报告,基于专业测评的技术、性能及市场优势深度分析