【题目】E. Segments Removal

【题意】给定n个数字,每次操作删除最长的连续相同数字(等长删最左),求全部删完的最少次数。n<=2*10^6,1<=ai<=10^9。

【算法】并查集+堆

【题解】将序列的相同数字段压缩,全部插入堆。那么每次操作删除堆顶,并尝试合并堆顶的前驱和后继,能合并就重新插入堆中。

在支持删除的序列中找前驱和后继,是经典的并查集实现。

具体而言,fa[i]表示 i 点左边(含自身)最近的未被删除的点,即把删除了的点全部并入左侧第一个未被删除的点,那么删除点x后fa[x]=find(fa[x]-1)。

前驱是find(fa[x]-1),后继只需要记录r[x]表示x点代表区间的最右端点,每次合并是:fa[y]=x,r[x]=r[y]。

如果能合并就重新插入堆中,容易发现堆中废弃的元素一定比新插入的更晚访问,所以废弃元素访问到就会是被删除的现象,一个元素被删除表现为find(x) ≠ x。

注意:删除的时候记得更新r[]。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cctype>
  4. #include<cmath>
  5. #include<queue>
  6. #include<stack>
  7. #include<set>
  8. #include<vector>
  9. #include<algorithm>
  10. #define ll long long
  11. #define lowbit(x) x&-x
  12. using namespace std;
  13. int read(){
  14. char c;int s=,t=;
  15. while(!isdigit(c=getchar()))if(c=='-')t=-;
  16. do{s=s*+c-'';}while(isdigit(c=getchar()));
  17. return s*t;
  18. }
  19. int min(int a,int b){return a<b?a:b;}
  20. int max(int a,int b){return a<b?b:a;}
  21. int ab(int x){return x>?x:-x;}
  22. //int MO(int x){return x>=MOD?x-MOD:x;}
  23. //void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
  24. /*------------------------------------------------------------*/
  25. const int inf=0x3f3f3f3f,maxn=;
  26.  
  27. int n,fa[maxn],a[maxn],tot,r[maxn];
  28. struct cyc{
  29. int id,ans,number,l;
  30. bool operator < (const cyc &a)const{
  31. return ans<a.ans||(ans==a.ans&&l>a.l);
  32. }
  33. }b[maxn];
  34. priority_queue<cyc>q;
  35. int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
  36. int main(){
  37. n=read();
  38. int x=;
  39. for(int i=;i<=n;i++)a[i]=read();
  40. for(int i=;i<=n;i++){
  41. x++;
  42. if(a[i]!=a[i+]){
  43. b[++tot]=(cyc){tot,x,a[i],i};
  44. x=;
  45. }
  46. }
  47. n=tot;
  48. for(int i=;i<=n;i++)fa[i]=i,r[i]=i;
  49. for(int i=;i<=n;i++)q.push(b[i]);
  50. for(int i=;i<=n;i++){
  51. cyc x=q.top();q.pop();
  52. while(find(x.id)!=x.id&&!q.empty())x=q.top(),q.pop();
  53. if(q.empty()){if(find(x.id)!=x.id)printf("%d",i-);else printf("%d",i);return ;}
  54. //printf("%d %d %d %d\n",x.id,x.ans,x.number,x.l);
  55. int f=find(x.id);
  56. fa[f]=find(f-);r[fa[f]]=r[f];
  57. int pre=find(f-),suc=find(r[f]+);
  58. if(pre==||suc==||b[pre].number!=b[suc].number)continue;
  59. fa[suc]=pre;
  60. b[pre].ans+=b[suc].ans;
  61. r[pre]=r[suc];
  62. q.push(b[pre]);
  63. }
  64. return ;
  65. }

【CodeForces】899 E. Segments Removal的更多相关文章

  1. 【CodeForces】899 F. Letters Removing

    [题目]F. Letters Removing [题意]给定只含小写字母.大写字母和数字的字符串,每次给定一个范围要求删除[l,r]内的字符c(l和r具体位置随删除变动),求m次操作后的字符串.n&l ...

  2. 【CodeForces】901 C. Bipartite Segments

    [题目]C. Bipartite Segments [题意]给定n个点m条边的无向连通图,保证不存在偶数长度的简单环.每次询问区间[l,r]中包含多少子区间[x,y]满足只保留[x,y]之间的点和边构 ...

  3. 【Luogu3602】Koishi Loves Segments(贪心)

    [Luogu3602]Koishi Loves Segments(贪心) 题面 洛谷 题解 离散区间之后把所有的线段挂在左端点上,从左往右扫一遍. 对于当前点的限制如果不满足显然会删掉右端点最靠右的那 ...

  4. 【CF429E】Points and Segments(欧拉回路)

    [CF429E]Points and Segments(欧拉回路) 题面 CF 洛谷 题解 欧拉回路有这样一个性质,如果把所有点在平面内排成一行,路径看成区间的覆盖,那么每个点被从左往右的覆盖次数等于 ...

  5. 【CF429E】Points and Segments 欧拉回路

    [CF429E]Points and Segments 题意:给你数轴上的n条线段$[l_i,r_i]$,你要给每条线段确定一个权值+1/-1,使得:对于数轴上的任一个点,所有包含它的线段的权值和只能 ...

  6. 【Codeforces】Round #491 (Div. 2) 总结

    [Codeforces]Round #491 (Div. 2) 总结 这次尴尬了,D题fst,E没有做出来.... 不过还好,rating只掉了30,总体来说比较不稳,下次加油 A:If at fir ...

  7. 【Codeforces】Round #488 (Div. 2) 总结

    [Codeforces]Round #488 (Div. 2) 总结 比较僵硬的一场,还是手速不够,但是作为正式成为竞赛生的第一场比赛还是比较圆满的,起码没有FST,A掉ABCD,总排82,怒涨rat ...

  8. 【CodeForces】601 D. Acyclic Organic Compounds

    [题目]D. Acyclic Organic Compounds [题意]给定一棵带点权树,每个点有一个字符,定义一个结点的字符串数为往下延伸能得到的不重复字符串数,求min(点权+字符串数),n&l ...

  9. 【Codeforces】849D. Rooter's Song

    [算法]模拟 [题意]http://codeforces.com/contest/849/problem/D 给定n个点从x轴或y轴的位置p时间t出发,相遇后按对方路径走,问每个数字撞到墙的位置.(还 ...

随机推荐

  1. inside、outside和dmz之间的访问

    现有条件:100M宽带接入,分配一个合法的IP(222.134.135.98)(只有1个静态IP是否够用?);Cisco防火墙PiX515e-r-DMZ-BUN1台(具有Inside.Outside. ...

  2. CentOS7安装.NET Core运行环境

    安装.NET Core ->首先需要删除以前安装的版本 -> 获取安装脚本 curl -sSL https://raw.githubusercontent.com/dotnet/cli/r ...

  3. Java ISO 8601时间格式转换

    common-lang包: String pattern = "YYYY-MM-dd'T'HH:mm:ssZZ"; System.out.println(DateFormatUti ...

  4. java网络编程(二)可中断套接字

    参考资料:java核心技术 卷II 为中断套接字操作,可使用java.nio包提供的SocketChannel类.可以使用如下方式打开SocketChannel: SocketChannel chan ...

  5. Simple上网导航--静态版

    现在的网址导航显然是一个针对小白用户的网页大全,新闻.笑话.视频.黄段子要什么有什么,一个网址导航竟然也要滑动好多页.其实80%的功能我都用不到,但是它们却时刻展现在我的眼前.所以我决定做一个简洁清晰 ...

  6. Eclipse中使用git提交代码,报错Testng 运行Cannot find class in classpath的解决方案

    一.查找原因方式 1.点击Project——>Clear...——>Build Automatically 2.查看问题 二.报错因素 1.提交.xlsx文件 2.提交时,.xlsx文件被 ...

  7. 卷积 & 杜教筛

    目录 卷积 杜教筛 前言:发现最近都没怎么写博客,,,赶紧发篇以前记的笔记凑凑数 卷积 卷积定义: 如果有数论函数\(f, g\), 那么它们卷积的第\(n\)项为\((f * g) (n)\),设这 ...

  8. [NOIP2008]双栈排序 【二分图 + 模拟】

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  9. 转载乙醇大师的appium简明教程

    appium简明教程(11)——使用resource id定位(仅支持安卓4.3以上系统) 乙醇 2014-06-28 21:01 阅读:16406 评论:21 appium简明教程(10)——控件定 ...

  10. bzoj3173: [Tjoi2013]最长上升子序列(fhqtreap)

    这题用fhqtreap可以在线. fhqtreap上维护以i结尾的最长上升子序列,数字按从小到大加入, 因为前面的数与新加入的数无关, 后面的数比新加入的数小, 所以新加入的数对原序列其他数的值没有影 ...