LINK:VMware和基站

一道 做法并不常见的题目 看起来很难写 其实set维护线段就可以解决了。

容易想到 第二个操作借用启发式合并可以得到一个很不错的复杂度 不过利用线段树维护这个东西 在区间覆盖的时候并不能很好的维护。

一个想法是 分块 不过操作比较ex.

第一个操作和第二个操作连在一起会非常的难以处理。

这里给出的做法是:使用set来维护整段的线段 这样在第一个区间覆盖的情况下 每次区间至多增加两个或者可能减少.

在第一步中就是logn的时间内可以维护了.不过细节较多我分类讨论了好几种情况。

考虑第二步 不妨每个基站都开一个set 利用启发式合并来做。

不过 不存在操作1的时候启发式合并 的总复杂度为nlog^2 存在操作1的时候 容易发现 每次区间最多增加两个 那么均摊到启发式合并上也是Qlog的时间。

对于第三步 直接在set中二分 分类讨论在左边还是右边即可.

挺难写的 三个函数都出了锅 第一个是少考虑了情况 第二个是 没有对s进行修改 第三个则是答案的情况存在小细节问题 写死我了.

const int MAXN=100010,G=3;
int n,Q;
struct wy
{
int l,r,id;
wy(int x,int y,int z){l=x;r=y;id=z;}
inline bool operator <(wy a)const {return l<a.l;}
};
set<wy>s;set<pii>g[MAXN];
set<wy>::iterator it;
set<pii>::iterator itt;
char a[10];
int f[MAXN];
inline void cover(int l,int r,int x)
{
it=s.upper_bound(wy(l,r,x));--it;
if((*it).l!=l)
{
int id=(*it).id;int L=(*it).l;int R=(*it).r;
g[id].erase(mk(L,R));g[id].insert(mk(L,l-1));
s.erase(it);s.insert(wy(L,l-1,id));
g[x].insert(mk(l,r));
s.insert(wy(l,r,x));it=s.find(wy(l,r,x));
if(R>r)
{
g[id].insert(mk(r+1,R));
s.insert(wy(r+1,R,id));
return;
}
if(R==r)return;++it;
while(it!=s.end())
{
R=(*it).r;
if(R<=r)
{
g[(*it).id].erase(mk((*it).l,(*it).r));
s.erase(it);it=s.find(wy(l,r,x));++it;
if(R==r)break;
}
else
{
id=(*it).id;
g[id].erase(mk((*it).l,R));
g[id].insert(mk(r+1,R));
s.erase(it);s.insert(wy(r+1,R,id));
break;
}
}
}
else
{
int id=(*it).id;int R=(*it).r;
//cout<<id<<endl;
g[id].erase(mk(l,(*it).r));
s.erase(it);s.insert(wy(l,r,x));it=s.find(wy(l,r,x));
g[x].insert(mk(l,r));
if(R>r)
{
g[id].insert(mk(r+1,R));
s.insert(wy(r+1,R,id));
return;
}
if(R==r)return;++it;
while(it!=s.end())
{
R=(*it).r;
//cout<<R<<endl;
if(R<=r)
{
g[(*it).id].erase(mk((*it).l,(*it).r));
s.erase(it);it=s.find(wy(l,r,x));++it;
if(R==r)break;
}
else
{
id=(*it).id;
g[id].erase(mk((*it).l,R));
g[id].insert(mk(r+1,R));
s.erase(it);s.insert(wy(r+1,R,id));
break;
}
}
}
}
inline void replace(int &x,int &y)
{
if(x==y)return;
if(g[x].size()>g[y].size())swap(x,y);
itt=g[x].begin();
while(itt!=g[x].end())
{
it=s.find(wy((*itt).F,(*itt).S,x));
s.erase(it);
s.insert(wy((*itt).F,(*itt).S,y));
g[y].insert(*itt);
++itt;
}
g[x].clear();
}
inline int ask(int D,int L,int R,int id)
{
if(!g[id].size())return -1;
int ans=-1;
itt=g[id].lower_bound(mk(L,0));
if(itt!=g[id].end()&&(*itt).F<=R)ans=max(ans,abs(D-(*itt).F));
if(itt!=g[id].begin())
{
--itt;
//cout<<(*itt).F<<' '<<(*itt).S<<endl;
if((*itt).F<=L&&(*itt).S>=L)ans=max(ans,abs(D-L));
}
itt=g[id].upper_bound(mk(R,n+1));
if(itt!=g[id].begin())
{
--itt;
if((*itt).F<=R&&(*itt).S>=R)ans=max(ans,abs(D-R));
if((*itt).S<=R&&(*itt).S>=L)ans=max(ans,abs(D-(*itt).S));
//cout<<(*itt).S<<' '<<(*itt).F<<endl;
}
return ans;
}
int main()
{
//freopen("1.in","r",stdin);
gt(n);gt(Q);
rep(1,n,i)g[i].insert(mk(i,i)),s.insert(wy(i,i,i)),f[i]=i;
rep(1,Q,i)
{
int x,y,z;
gc(a);gt(x);gt(y);
if(a[1]=='c')gt(z),cover(x,y,f[z]);
if(a[1]=='r')replace(f[x],f[y]);
if(a[1]=='f')gt(z),put(ask(x,max(x-y,1),min(x+y,n),f[z]));
}
return 0;
}

牛客挑战赛40 VMware和基站 set 二分 启发式合并 区间覆盖的更多相关文章

  1. 5.15 牛客挑战赛40 C 小V和字符串 数位dp 计数问题

    LINK:小V和字符串 容易想到只有1个数相同的 才能有贡献. 知道两个01串 那么容易得到最小步数 大体上就是 第一个串的最前的1和第二个串最前的1进行匹配. 容易想到设f[i][j]表示 前i位1 ...

  2. 5.15 牛客挑战赛40 E 小V和gcd树 树链剖分 主席树 树状数组 根号分治

    LINK:小V和gcd树 时限是8s 所以当时好多nq的暴力都能跑过. 考虑每次询问暴力 跳父亲 这样是nq的 4e8左右 随便过. 不过每次跳到某个点的时候需要得到边权 如果直接暴力gcd的话 nq ...

  3. 5.15 牛客挑战赛40 B 小V的序列 关于随机均摊分析 二进制

    LINK:小V的序列 考试的时候 没想到正解 于是自闭. 题意很简单 就是 给出一个序列a 每次询问一个x 问序列中是否存在y 使得x^y的二进制位位1的个数<=3. 容易想到 暴力枚举. 第一 ...

  4. 牛客挑战赛 39 牛牛与序列 隔板法 容斥 dp

    LINK:牛牛与序列 (牛客div1的E题怎么这么水... 还没D难. 定义一个序列合法 当且仅当存在一个位置i满足 $a_i>a_,a_j<a_$且对于所有的位置i,$1 \leq a_ ...

  5. 牛客练习赛16 F 选值【二分/计数】

    链接:https://www.nowcoder.com/acm/contest/84/F 来源:牛客网 题目描述 给定n个数,从中选出三个数,使得最大的那个减最小的那个的值小于等于d,问有多少种选法. ...

  6. 牛客练习赛34 little w and Segment Coverage (差分区间)

    链接:https://ac.nowcoder.com/acm/contest/297/C来源:牛客网 题目描述 小w有m条线段,编号为1到m. 用这些线段覆盖数轴上的n个点,编号为1到n. 第i条线段 ...

  7. 牛客小白月赛16 小石的妹子 二分 or 线段树

    牛客小白月赛16 这个题目我AC之后看了一下别人的题解,基本上都是线段树,不过二分也可以. 这个题目很自然就肯定要对其中一个进行排序,排完序之后再处理另外一边,另一边记得离散化. 怎么处理呢,你仔细想 ...

  8. 牛客挑战赛 30 A 小G数数

    题目链接:https://ac.nowcoder.com/acm/contest/375/A 分析:我写的时候竟然把它当成了DP....... 还建了个结构体DP数组,保存一二位,不知道当时脑子在抽啥 ...

  9. 良心送分题(牛客挑战赛35E+虚树+最短路)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 给你一棵树,然后把这棵树复制\(k\)次,然后再添加\(m\)条边,然后给你起点和终点,问你起点到终点的最短路. 思路 由于将树复制\(k\) ...

随机推荐

  1. 状压DP之愤怒的小鸟

    题目 传送们P2831 题目较长,不加以赘述 直接步入正题 首先是数学知识,我们可以先根据给出的任意两只猪构建相应的抛物线,同时再构建完之后应判断抛物线的合法性(比如a小于0啊,等等),公式推演就不在 ...

  2. 洛谷 P1640 SCOI2010 连续攻击游戏 并查集

    题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备 ...

  3. 查看windows操作系统的默认编码

    转自:https://blog.csdn.net/zp357252539/article/details/79084480/ 在Windows平台下,进入DOS窗口,输入:chcp 可以得到操作系统的 ...

  4. Django---进阶4

    目录 CBV源码剖析 模版语法传值 过滤器(过滤器只能最多有两个参数) 标签 自定义过滤器.标签.inclusion_tag 模版的继承 模版的导入 作业 CBV源码剖析 # 你自己不要修改源码 除了 ...

  5. Talk About AWS Aurora for MySQL max_connections parameter Calculation | 浅谈AWS Aurora for MySQL数据库中 max_connections参数的计算

    1. The Problem | 现象 When connect to the product environment database of my company, the Navicat show ...

  6. day11 文件操作(上)

    目录 一.什么是文件 二.为何要用文件 三.如何使用文件 3.1文件操作的基本流程 3.2资源回收with上下文管理 3.3指定操作文本的字符编码 四.文件的操作模式 4.1控制文件读写操作的模式(t ...

  7. python中os模块用法大全

    os.listdir(dirname):列出dirname下的目录和文件 os.getcwd():获得当前工作目录 os.chdir(dirname):改变工作目录到dirname os.path.r ...

  8. python 并发专题(四):yield以及 yield from

    一.yield python中yield的用法很像return,都是提供一个返回值,但是yield和return的最大区别在于,return一旦返回,则代码段执行结束,但是yield在返回值以后,会交 ...

  9. POJ 1095 Trees Made to Order 最详细的解题报告

    题目来源:Trees Made to Order 题目大意:根据下面的规则给一棵二叉树编号: 规则1:如果二叉树为空,则编号为0: 规则2:如果二叉树只有一个节点,则编号为1: 规则3:所有含有m个节 ...

  10. Unity-JobSystom

    什么是Job System? 一个job system通过创建jobs而不是线程来管理多线程的代码.Job是一个小的工作单元,不等同线程.管理运行在多个核心上的一组工人线程(worker thread ...