提一下,博主的英语四级过了,就是这么6(虽然考了两回)
区间合并:这类题目会询问区间中满足条件的连续最长区间,所以PushUp的时候需要对左右儿子的区间进行合并,因为有可能合并之后连续最长区间比左右儿子的都长。大概就是这样。上题:
-
总时间限制:
- 1000ms 内存限制:
- 65535kB
-
描述
-
有一个苦逼的种树人XX,需要种一排树,为什么说苦逼呢?因为总有一些熊孩子去把树苗拔掉(具体拔掉做什么,你们可以YY一下)。为了简化问题,把可以种树的位置编号为1-n。XX每次选择一个位置种树(如果已经有树了,则忽略),而熊孩子每次也选择一个位置拔树(如果没有树,则忽略)。现在XX想知道每次种树或者拔树后的连续有树的区间的最长长度。
输入
-
多组数据(大约10组)。对于每组数据:
第一行n,m;
接下来m行,每行q,a;
其中,q为1时表示XX种树,q为2时表示熊孩子拔树,a表示位置。
数据范围:1<=n,m<=10000,1<=q<=2,1<=a<=n。
输出
- 对于每组数据,输出m行,每次操作后的结果。 样例输入
-
4 5 1 1 1 3 1 4 2 4 1 2
样例输出
-
1 1 2 1 3
提示
- 开始状态都没有种树
-
- 这道题比较简单,因为还没涉及延迟更新,只涉及最基本的点更新,贴代码:
-
好了,睡觉了,明天还有培训。#include<stdio.h> #define MAX 10000 struct node { int l,r,mid; int lMax,rMax; //分别是某个区间内左边界与右边界最长连续子区间长度 int max; //某个区间内最长连续子区间长度 }; int Max(int a,int b) { if(a>b)return a; else return b; } node t[MAX*4]; int n; void BuildTree(int i,int l,int r) { t[i].l=l; t[i].r=r; if(l==r) { t[i].max=0; t[i].lMax=t[i].rMax=0; return; } t[i].mid=(l+r)/2; BuildTree(i*2,l,t[i].mid); BuildTree(i*2+1,t[i].mid+1,r); t[i].max=0; t[i].lMax=t[i].rMax=0; } void PushUp(int i) //合并区间核心代码 { t[i].max=Max(t[i*2].rMax+t[i*2+1].lMax, Max(t[i*2+1].max,t[i*2].max)); if(t[i*2].r-t[i*2].l+1==t[i*2].max) t[i].lMax=t[i*2].max+t[i*2+1].lMax; else t[i].lMax=t[i*2].lMax; if(t[i*2+1].r-t[i*2+1].l+1==t[i*2+1].max) t[i].rMax=t[i*2+1].max+t[i*2].rMax; else t[i].rMax=t[i*2+1].rMax; } void Update(int i,int index,int num) { if(t[i].l==t[i].r) { if(t[i].max==0&&num==1) t[i].max=t[i].rMax=t[i].lMax=1; else if(t[i].max==1&&num==2) t[i].max=t[i].rMax=t[i].lMax=0; return; } if(index<=t[i].mid)Update(i*2,index,num); else Update(i*2+1,index,num); PushUp(i); } int main() { int m,i,q,a; while(scanf("%d%d",&n,&m)!=EOF) { BuildTree(1,1,n); for(i=0;i<m;i++) { scanf("%d%d",&q,&a); Update(1,a,q); printf("%d\n",t[1].max); } } return 0; }