题目链接:http://codeforces.com/contest/1154/problem/E

题意:两个人轮流取最大值与旁边k个数,问最后这所有的数分别被谁给取走了

分析:看这道题一点思路都没有,想不到模拟链表也该能想到线段树的啊

大部分AC代码是模拟链表的,写起来也更快,但我线段树很不熟,线段树的代码也写一份吧

另外,以后要养成一种习惯,除了主函数定义int main里有int外,其他地方统一用ll了,不要自己给自己挖坑。。。。。

线段树:

意识到是线段树后我建树部分就拿不准怎么做,事实上可以一开始先输入在数组里,建树部分代码稍微改动一下就好

代码本身不难,就着注释读一读很明显,要注意的部分我也提到了

这次的模板我是用的CF大佬的,感觉很好用

然后快读和快写效果十分显著,直接从102ms变成了62ms

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int inf=<<;
  5. const int maxn=*1e5+;
  6. const double pi=acos(-);
  7. const int mod=1e9+;
  8. int a[maxn],ans[maxn],pre[maxn],nxt[maxn],pos[maxn];
  9. struct node
  10. {
  11. int l,r,sum,lazy;
  12. }tree[*maxn];
  13. inline ll read(){
  14. ll x=,tmp=;
  15. char ch=getchar();
  16. while(!isdigit(ch)){
  17. if(ch=='-') tmp=-;
  18. ch=getchar();
  19. }
  20. while(isdigit(ch)){
  21. x=(x<<)+(x<<)+ch-;
  22. ch=getchar();
  23. }
  24. return tmp*x;
  25. }
  26.  
  27. inline void write(ll x){
  28. ll y=,len=;
  29. while(y<=x){
  30. y=(y<<)+(y<<);
  31. len++;
  32. }
  33. while(len--){
  34. y/=;
  35. putchar(x/y+);
  36. x%=y;
  37. }
  38. }
  39. inline void pushdown(ll p){
  40. if(tree[p].lazy){
  41. tree[p<<].sum=; tree[p<<].lazy=;
  42. tree[p<<|].sum=; tree[p<<|].lazy=;
  43. tree[p].lazy=;
  44. }
  45. }
  46.  
  47. void build(ll p,ll l,ll r){
  48. tree[p].l=l; tree[p].r=r;
  49. if(l==r){
  50. tree[p].sum=a[l];
  51. return;
  52. }
  53. ll mid=(l+r)>>;
  54. build(p<<,l,mid);
  55. build(p<<|,mid+,r);
  56. tree[p].sum=max(tree[p<<].sum,tree[p<<|].sum);
  57. }
  58. void update(ll p,ll l,ll r){
  59. if(l<=tree[p].l&&tree[p].r<=r){
  60. tree[p].sum=; tree[p].lazy=;
  61. return;
  62. }
  63. pushdown(p);
  64. ll mid=(tree[p].l+tree[p].r)>>;
  65. if(l<=mid) update(p<<,l,r);
  66. if(r>mid) update(p<<|,l,r);
  67. tree[p].sum=max(tree[p<<].sum,tree[p<<|].sum);
  68. }
  69. ll query(ll p,ll l,ll r){
  70. if(l<=tree[p].l&&tree[p].r<=r) return tree[p].sum;
  71. pushdown(p);
  72. ll mid=(tree[p].l+tree[p].r)>>,ans=;
  73. if(l<=mid) ans=max(ans,query(p<<,l,r));
  74. if(r>mid) ans=max(ans,query(p<<|,l,r));
  75. tree[p].sum=max(tree[p<<].sum,tree[p<<|].sum);
  76. return ans;
  77. }
  78. int main(){
  79. ll n,k;scanf("%I64d%I64d",&n,&k);
  80. nxt[]=,pre[n+]=n;//这点要注意别忘了
  81. for(ll i=;i<=n;i++){
  82. a[i]=read();
  83. pos[a[i]]=i;
  84. pre[i]=i-;
  85. nxt[i]=i+;//咋一看似乎没必要,但取走操作之后可能第5个人的前一个人就不是第四个人而是第二个人了
  86. }
  87. build(,,n);
  88. ll now=;//这个now是第几组的意思,弄成0,1方便异或更改
  89. while(){
  90. ll x=query(,,n);
  91. if(x<=) break;
  92. ans[pos[x]]=now;
  93. ll l=pos[x],r=pos[x];
  94. for(ll i=;i<=k;i++){
  95. if(pre[l]==) break;
  96. else {
  97. l=pre[l];
  98. ans[l]=now;
  99. }
  100. }
  101. for(ll i=;i<=k;i++){
  102. if(nxt[r]==n+) break;
  103. else{
  104. r=nxt[r];
  105. ans[r]=now;
  106. }
  107. }
  108. update(,l,r);
  109. pre[nxt[r]]=pre[l];
  110. nxt[pre[l]]=nxt[r];//这个更新很灵性吧,就是把最右边的前一位更改为最左边的前一位,最左边的后一位
  111. //更改为最右边的后一位,也就是把中间被选走的数的影响给剔除,也是nxt和pre数组的意义所在
  112. now^=;
  113. }
  114. for(int i=;i<=n;i++)write(ans[i]+);
  115. putchar('\n');
  116. return ;
  117. }

模拟链表:

就是用两个优先队列来模拟链表,优先队列内的数是按顺序从大到小存好的,刚好满足要求

看懂了线段树看这个肯定没有一点问题:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int inf=<<;
  5. const int maxn=*1e5+;
  6. const double pi=acos(-);
  7. const int mod=1e9+;
  8. typedef pair<int,int> P;
  9. int pre[maxn],nxt[maxn],a[maxn],ans[maxn];
  10. priority_queue<P> p,q;
  11. int main(){
  12. int n,k;scanf("%d%d",&n,&k);
  13. for(int i=;i<=n;i++){
  14. scanf("%d",&a[i]);
  15. pre[i]=i-,nxt[i]=i+;
  16. q.push(P(a[i],i));
  17. }
  18. int opt=;
  19. while(!q.empty()){
  20. while(p.size()&&q.top()==p.top()) q.pop(),p.pop();
  21. if(q.empty()) break;
  22. int m,i,j;
  23. //求前缀
  24. for(i=pre[q.top().second],j=;j<=k&&i;j++,i=pre[i]){
  25. p.push(P(a[i],i));
  26. ans[i]=opt+;
  27. }
  28. for(m=nxt[q.top().second],j=;j<=k&&m;j++,m=nxt[m]){
  29. p.push(P(a[m],m));
  30. ans[m]=opt+;
  31. }
  32. ans[q.top().second]=opt+;q.pop();
  33. opt^=;
  34. nxt[i]=m,pre[m]=i;
  35. }
  36. for(int i=;i<=n;i++)cout<<ans[i];
  37. cout<<endl;
  38. return ;
  39. }

CF 552(div 3) E Two Teams 线段树,模拟链表的更多相关文章

  1. CF #296 (Div. 1) A. Glass Carving 线段树

    A. Glass Carving time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  2. 【CF280D】 k-Maximum Subsequence Sum ,线段树模拟费用流

    昨天考试被教育了一波.为了学习一下\(T3\)的科技,我就找到了这个远古时期的\(cf\)题(虽然最后\(T3\)还是不会写吧\(QAQ\)) 顾名思义,这个题目其实可以建成一个费用流的模型.我们用流 ...

  3. hdu_5818_Joint Stacks(线段树模拟)

    题目链接:hdu_5818_Joint Stacks 题意: 给你两个栈,多了个合并操作,然后让你模拟 题解: 很容易想到O(1)的单个栈操作,O(n)的合并操作,这样肯定超时,所以我们要将时间复杂度 ...

  4. 2019牛客暑期多校训练营(第八场)E:Explorer(LCT裸题 也可用线段树模拟并查集维护连通性)

    题意:给定N,M,然后给出M组信息(u,v,l,r),表示u到v有[l,r]范围的通行证有效.问有多少种通行证可以使得1和N连通. 思路:和bzoj魔法森林有点像,LCT维护最小生成树.  开始和队友 ...

  5. CF 666E Forensic Examination 【SAM 倍增 线段树合并】

    CF 666E Forensic Examination 题意: 给出一个串\(s\)和\(n\)个串\(t_i\),\(q\)次询问,每次询问串\(s\)的子串\(s[p_l:p_r]\)在串\(t ...

  6. Codeforces Round #222 (Div. 1) D. Developing Game 线段树有效区间合并

    D. Developing Game   Pavel is going to make a game of his dream. However, he knows that he can't mak ...

  7. Codeforces Round #275 Div.1 B Interesting Array --线段树

    题意: 构造一个序列,满足m个形如:[l,r,c] 的条件. [l,r,c]表示[l,r]中的元素按位与(&)的和为c. 解法: 线段树维护,sum[rt]表示要满足到现在为止的条件时该子树的 ...

  8. CF 197 DIV2 Xenia and Bit Operations 线段树

    线段树!!1A 代码如下: #include<iostream> #include<cstdio> #define lson i<<1 #define rson i ...

  9. Codeforces Round #244 (Div. 2) B. Prison Transfer 线段树rmq

    B. Prison Transfer Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/pro ...

随机推荐

  1. 记一次ORACLE无法启动登陆事故

    打开XSHELL 登陆ORACLE用户 1.sqlplus scott/scott 提示登陆失败 2.sqplus / as sysdba 启动数据库提示 3.查找日志 操作日志:$ORACLE_HO ...

  2. ngx-admin with Asp.net Core 2.0, possibly plus OrchardCore

    1 Download ngx-admin from https://github.com/akveo/ngx-admin 2 Create a new Web Application in vs201 ...

  3. spring boot + vue + element-ui全栈开发入门——项目部署

     前言 常用的部署方式有两种: 1.是把生成好的静态页面放到spring boot的static目录下,与打包后的spring boot项目一起发布,当spring boot运行起来后,自然而然就能访 ...

  4. WPF Combobox数据绑定 Binding

    combobox数据绑定List链表集合区分显示值与选择的值 整体效果: 根据combobox选择情况分别打印选取值与显示值 代码: Windows窗体: <Window x:Class=&qu ...

  5. 2018-2019-2 网络对抗技术 20165335 Exp3 免杀原理与实践

    一.免杀原理与基础知识: (1)杀软是如何检测出恶意代码的? 检测特征码:特征码就是一般程序都不会有的代码,而后门有的那种特别的数据,而一个程序,应用有这种代码,数据的话,就直接判定为恶意代码. 主流 ...

  6. 移动端开发调试工具神器--Weinre使用方法

    前端开发调试必备: DOM操作断点调试: debugger断点调试: native方法hook(个人暂时还没有试过,不知效果如何): 远程映射本地测试: Weinre移动调试(详细介绍): 像Dom断 ...

  7. C类网络子网掩码速查

    子网掩码 网络位数 子网数量 可用主机数 255.255.255.252 30 64 2 255.255.255.248 29 32 6 255.255.255.240 28 16 14 255.25 ...

  8. Springboot 配置类( @Configuration) 不能使用@Value注解从application.propertyes中加载值以及Environment为null解决方案

    最近遇到个场景,需要在使用@Bean注解定义bean的时候为对象设置一些属性,比如扫描路径,因为路径经常发布新特性的时候需要修改,所以就计划着放在配置文件中,然后通过@ConfigurationPro ...

  9. CORS:source,princple,implimentation in Spring

    CORS = Cross-Origin Resource Sharing          一种跨域访问技术 什么是 Origin 要理解CORS,首先得理解什么是 “Origin”.参见RFC645 ...

  10. Markdown介绍

    如何使用.md文件 本文档为Markdown格式,建议利用Visual Studio Code+ Markdown All in One插件修改.参考链接:基础mdbasic,高级mdextended