【线段树】COCI2010-2011(CONTEST#6)[STEP]题解
来源:互联网 发布:无法无天小说吾知 编辑:程序博客网 时间:2024/06/12 05:21
题目概述
有一个长度为n的序列,刚开始全是L,给出te个操作,每次操作给出一个x,表示把x从L改为R(R改为L)。每次操作后询问最长的字串,这个字串需要满足相邻位置符号不同。
解题报告
刚开始我是这么想的:把序列分块成一片片满足的区域,比如LRRLRRRLRLRL被分为|LR|RLR|R|RLRLRL|。然后记录father[i]和r[i]表示i所在区域最左边的编号和i能够向右推的个数,用线段树维护这些区域(加加减减,改来改去),这种做法常数显然很大,还容易写错,可想而知我华丽丽的炸了(WA+TLE)。
后来,Lynstery飘过来说:“这种垃圾题”,然后告诉了我强的不行的做法:序列相邻两个之间如果是相同的,就记为0,否则记为1,举个例子:
L R R L R R R L R L R L 1 0 1 1 0 0 1 1 1 1 1
那么求最长子串就转化为求最长连续1的个数。
接下来还是用线段树处理,每个节点记录MAX,pre,suf表示最长子串,最长前缀和最长后缀,由于每次只是单点修改,所以维护这三个信息是比较简单的:
pre=左儿子preif (左儿子MAX=左儿子区间跨度) pre=左儿子MAX+右儿子pre//左儿子MAX=左儿子区间跨度其实等价于左儿子能够全选suf=右儿子sufif (右儿子MAX=右儿子区间跨度) suf=右儿子MAX+左儿子sufMAX=max(左儿子MAX,右儿子MAX,pre,suf,左儿子suf+右儿子pre)
那么最大值就是MAX[1]。
示例程序
#include<cstdio>#include<algorithm>using namespace std;const int maxn=200000,maxt=4*maxn,MAXINT=((1<<30)-1)*2+1;int n,te;bool vis[maxn+5];struct SegmentTree{ int l[maxt+5],r[maxt+5],MAX[maxt+5],pre[maxt+5],suf[maxt+5]; void Build(int L,int R,int p=1) { l[p]=L;r[p]=R;MAX[p]=pre[p]=suf[p]=0; if (L==R) return;int mid=L+(R-L>>1); Build(L,mid,p<<1);Build(mid+1,R,p<<1|1); } void Pushup(int p) { pre[p]=pre[p<<1]; if (MAX[p<<1]==r[p<<1]-l[p<<1]+1) pre[p]=MAX[p<<1]+pre[p<<1|1]; suf[p]=suf[p<<1|1]; if (MAX[p<<1|1]==r[p<<1|1]-l[p<<1|1]+1) suf[p]=suf[p<<1]+MAX[p<<1|1]; MAX[p]=max(max(pre[p],suf[p]),max(MAX[p<<1],MAX[p<<1|1])); MAX[p]=max(MAX[p],suf[p<<1]+pre[p<<1|1]); } void Update(int pos,int k,int p=1) { if (pos<l[p]||r[p]<pos) return; if (l[p]==r[p]) {MAX[p]=pre[p]=suf[p]=k;return;} Update(pos,k,p<<1);Update(pos,k,p<<1|1); Pushup(p); }};SegmentTree tr;bool Eoln(char ch) {return ch==10||ch==13||ch==EOF;}char readc(){ static char buf[100000],*l=buf,*r=buf; if (l==r) r=(l=buf)+fread(buf,1,100000,stdin); if (l==r) return EOF; else return *l++;}int readi(int &x){ int tot=0,f=1;char ch=readc(),lst='+'; while ('9'<ch||ch<'0') {if (ch==EOF) return EOF;lst=ch;ch=readc();} if (lst=='-') f=-f; while ('0'<=ch&&ch<='9') tot=tot*10+ch-48,ch=readc(); x=tot*f; return Eoln(ch);}int main(){ freopen("step.in","r",stdin); freopen("step.out","w",stdout); readi(n);readi(te);tr.Build(1,n-1); while (te--) { int x;readi(x); if (x>1) tr.Update(x-1,vis[x-1]^=1); if (x<n) tr.Update(x,vis[x]^=1); printf("%d\n",tr.MAX[1]+1); } return 0;}
阅读全文
1 0
- 【线段树】COCI2010-2011(CONTEST#6)[STEP]题解
- COCI 2010/2011 6th round--STEP【线段树】
- 线段树-题解
- HDU 3954 Level up 2011 Alibaba Programming Contest 线段树
- 2011 Heilongjiang collegiate programming contest题解报告
- 线段树·题解报告
- [线段树][CODEVS 1080]题解
- POJ3264Balanced Lineup题解-线段树
- AcceptCM Contest - 1 题解
- HDU 3974 Assign the task 2011 Multi-University Training Contest 14 - Host by FZU 线段树
- (hdu step 5.3.1)敌兵布阵(线段树:单点更新)
- 2016 Multi-University Training Contest 6题解报告
- Fudan University Local Contest 2012 题解(划分树)
- 线段树的经典题目及题解
- 【POJ】【P3237】【Tree】【题解】【树链剖分+线段树】
- 【BZOJ】【P2104】【Wc2009】【shortest】【题解】【线段树】
- 【BZOJ】【P3165】【Heoi2013】【Segment】【题解】【线段树】
- HDU 3255 题解 线段树+扫描线
- ASM(Active Shape Model)算法介绍
- Flink学习笔记 --- Basic Concepts整理笔记
- react native环境搭建+genymotion
- MyBatis的事务处理的方式
- 【P1010-幂次方】解题记录
- 【线段树】COCI2010-2011(CONTEST#6)[STEP]题解
- Python的编码问题
- 分治算法——快速排序
- 教你如何学习自动化测试
- 计算机网络基础知多少
- Project facet Java 1.8 is not supported by target runtime Apache Tomcat v8.0解决
- Android adb shell KeyCode列表
- 算法练习_LeetCode_链表1
- leetcode--max-points-on-a-line