[国家集训队2012]middle(陈立杰)
我是萌萌的传送门
我是另一个萌萌的传送门
脑残错误毁一下午……
其实题解早就烂大街了,然而很久之前我只知道是二分答案+主席树却想不出来这俩玩意儿怎么一块儿用的……今天又翻了几篇题解才恍然大悟,是把权值排序之后依次插入序列,用主席树维护连续和……(我菜爆了……= =)
还是讲讲大体思路吧,首先二分答案M,把>=M的元素标为1,<M的标为-1,然后判定满足条件的最大子串和是否>=0,是则说明判定标准可行,否则不可行,调整下一次二分即可。但是直接暴力标记肯定会T,所以尝试对所有判定标准维护线段树来求最大子串和,然而内存开不下……考虑到如果把元素依次插入的话每次只会修改一个值,那么就把元素排序后依次插入线段树中,可持久化压内存即可。
一点细节:
鉴于子序列中间那段是肯定会用到的,所以直接拆成三段,前一段求最大后缀和,中间直接求和,后一段求最大前缀和,合并即可。因为最大前缀/后缀和是非严格最大(可以一个都不选),所以需要把b和c归到中间那段(保证一定会用上)。
贴个bzoj的代码:
![](/assets/blank.gif)
![](/assets/blank.gif)
1 /************************************************************** 2 Problem: 2653 3 User: hzoier 4 Language: C++ 5 Result: Accepted 6 Time:936 ms 7 Memory:101108 kb 8 ****************************************************************/ 9 10 #include<cstdio> 11 #include<cstring> 12 #include<algorithm> 13 using namespace std; 14 const int maxn=20010; 15 struct node{ 16 int sum,prefix,suffix; 17 node *lc,*rc; 18 void refresh(){ 19 sum=lc->sum+rc->sum; 20 prefix=max(lc->prefix,lc->sum+rc->prefix); 21 suffix=max(rc->suffix,rc->sum+lc->suffix); 22 } 23 }null[maxn<<8],*ptr=null; 24 struct A{ 25 int d,id; 26 bool operator<(const A &a)const{return d<a.d;} 27 }a[maxn]; 28 void build(int,int,node*&); 29 void modify(int,int,node*&,node*&); 30 void qsum(int,int,node*); 31 void qprefix(int,int,node*); 32 void qsuffix(int,int,node*); 33 node *root[maxn]; 34 int n,m,x,d,s,t,q[5],tmp,sum,ans,lastans=0,L,R,M; 35 int main(){ 36 null->lc=null->rc=null; 37 null->sum=null->prefix=null->suffix=0; 38 scanf("%d",&n); 39 fill(root,root+n+1,(node*)null); 40 build(1,n,root[0]); 41 for(int i=1;i<=n;i++){ 42 scanf("%d",&a[i].d); 43 a[i].id=i; 44 } 45 sort(a+1,a+n+1); 46 for(int i=1;i<=n;i++){ 47 x=a[i].id; 48 modify(1,n,root[i],root[i-1]); 49 } 50 scanf("%d",&m); 51 while(m--){ 52 for(int i=0;i<4;i++){ 53 scanf("%d",&q[i]); 54 q[i]+=lastans;q[i]%=n;q[i]++; 55 } 56 sort(q,q+4); 57 L=1;R=n; 58 while(L<=R){ 59 M=(L+R)>>1; 60 ans=0; 61 s=q[1];t=q[2]; 62 qsum(1,n,root[M-1]); 63 s=q[0];t=q[1]-1; 64 sum=tmp=0; 65 if(s<=t)qsuffix(1,n,root[M-1]); 66 ans+=sum; 67 s=q[2]+1;t=q[3]; 68 sum=tmp=0; 69 if(s<=t)qprefix(1,n,root[M-1]); 70 ans+=sum; 71 if(ans>=0)L=M+1; 72 else R=M-1; 73 } 74 printf("%d\n",lastans=a[R].d); 75 } 76 return 0; 77 } 78 void build(int l,int r,node *&rt){ 79 rt=++ptr; 80 rt->sum=rt->prefix=rt->suffix=r-l+1; 81 if(l==r){ 82 rt->lc=rt->rc=null; 83 return; 84 } 85 int mid=(l+r)>>1; 86 build(l,mid,rt->lc); 87 build(mid+1,r,rt->rc); 88 } 89 void modify(int l,int r,node *&rt,node *&pr){ 90 *(rt=++ptr)=*pr; 91 if(l==r){ 92 rt->sum=-1; 93 rt->prefix=rt->suffix=0; 94 return; 95 } 96 int mid=(l+r)>>1; 97 if(x<=mid)modify(l,mid,rt->lc,pr->lc); 98 else modify(mid+1,r,rt->rc,pr->rc); 99 rt->refresh(); 100 } 101 void qsum(int l,int r,node *rt){ 102 if(s<=l&&t>=r){ 103 ans+=rt->sum; 104 return; 105 } 106 int mid=(l+r)>>1; 107 if(s<=mid)qsum(l,mid,rt->lc); 108 if(t>mid)qsum(mid+1,r,rt->rc); 109 } 110 void qprefix(int l,int r,node *rt){ 111 if(s<=l&&t>=r){ 112 sum=max(sum,tmp+rt->prefix); 113 tmp+=rt->sum; 114 return; 115 } 116 int mid=(l+r)>>1; 117 if(s<=mid)qprefix(l,mid,rt->lc); 118 if(t>mid)qprefix(mid+1,r,rt->rc); 119 } 120 void qsuffix(int l,int r,node *rt){ 121 if(s<=l&&t>=r){ 122 sum=max(sum,tmp+rt->suffix); 123 tmp+=rt->sum; 124 return; 125 } 126 int mid=(l+r)>>1; 127 if(t>mid)qsuffix(mid+1,r,rt->rc); 128 if(s<=mid)qsuffix(l,mid,rt->lc); 129 }
View Code
话说这份代码跑得还挺快,哈哈……
写题过程中出了两个脑残错误,两个多小时就这么搭进去了……
1.如果序列长度为偶数,按题意中位数应为中间的两个数中较大的那个,然而我一开始读成了较小的那个,然后就死活弄不清脑子一片混乱……
2.注意到求最大后缀和最后一句if(s<=mid)了没……一开始写成了if(t<=mid),然后澄清完了题意还各种跟暴力拍不上,我特么都快崩溃了……后来发现是这个脑残错误,我只想说: $%*&$^%&#$%!@&#@^&*!%$^#@%*……
看看这惨烈的提交记录……
下次写题一定要先澄清题意……脑残怎么治啊……
转载于:https://www.cnblogs.com/hzoier/p/6266078.html
[国家集训队2012]middle(陈立杰)相关推荐
- [国家集训队2012]tree(陈立杰)
1764. [国家集训队2012]tree(陈立杰) ★★★ 输入文件: nt2012_tree.in 输出文件: nt2012_tree.out 简单对比 时间限制:3 s 内存限 ...
- BZOJ2654/COGS1764 [2012国家集训队]tree(陈立杰) [生成树,二分]
BZOJ传送门,COGS传送门 tree Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V, ...
- [国家集训队2012]电子对撞机nbsp;解题…
国家集训队2012 电子对撞机(刘洪轩)解题报告 题目: 见http://cogs.pro/cogs/problem/problem.php?pid=1784 Q国最近科学技术不断进步,经过不懈努力, ...
- tree(陈立杰)[国家集训队2012]
时间限制:3.0s 内存限制:1.0GB [大意] 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. [输入格式] 第一行V,E,ne ...
- BZOJ2568 [国家集训队2012]比特集合
Description 比特集合是一种抽象数据类型(Abstract Data Type) ,其包含一个集合S,并支持如下几种操作: INS M : 将元素 M 插入到集合S中: DEL M : 将集 ...
- cogs1799 [国家集训队2012]tree(伍一鸣)
LCT裸题 注意打标记之间的影响就是了 这个膜数不会爆unsigned int #include<cstdio> #include<cstdlib> #include<a ...
- 数据结构(动态树):[国家集训队2012]tree(伍一鸣)
[问题描述] 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原 ...
- 【国家集训队】middle
题意:给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数. 强制在线. 思路:首先考虑二分答案,判断可行的方法则是看是否小于他的 ...
- bzoj 2653: middle(陈立杰)
首先膜拜clj... 这道题初看没头绪,看了诸多题解后,发现时先二分,在把大于等于它的为1,小于它的为-1,一段区间最大连续和非负就行 然后想了N久都没想通,终于,在昨天在外拜年时想通了,就是以每个数 ...
最新文章
- IOCP , kqueue , epoll ... 有多重要?
- 研究速递:预测学习——神经元高效运作的最佳策略
- 您的关注是我最大的快乐
- pyinstaller3.5 和 python 3.8 不兼容
- linux grep 详细深入学习
- 推荐系统炼丹笔记:边缘计算+奉送20个推荐系统强特
- k5b型计算机联锁知识,DS6-K5B计算机联锁系统日常维护注意事项
- [数据结构-严蔚敏版]P64循环队列-队列的顺序存储结构
- python字典键值对转化为相应的变量名和变量值
- C++或C 实现AES ECB模式加密解密,支持官方验证
- boost库 bind/function的使用
- 【英语学习】【Daily English】U10 Education L01 Is this certificate a must?
- lpsolve java_如何使用LpSolve在R中设置线性编程优化?
- Ubuntu18.04 + CUDA10.0 + tensorflow-gpu 安装过程
- [VB]用记录集填充表格函数
- 【阿里巴巴】面向2022届应届生,阿里启动史上最大规模校招
- WORD里边替换所有中文
- Linux系统下下载Tomcat详细步骤。
- 家庭财务软件的概要分析
- 厦门大学计算机专业录取分数线2019,厦门大学录取分数线2019年各省及各专业分数线...