HDU1540
题意:求区间最大连续点的个数
题解:
-
我们要找某个点,那么就要找到左边最近被破坏(在左边编号是最大的)maxd的和右边最近被破坏的(在右边编号是最小的)mind,那么ans = min - max - 1
-
所以维护区间的最大值和最小值
-
默认最大值是0,最小值是n+1
-
每次破坏了之后这个点的最大值和最小值就更新成它本身
-
特殊情况下询问的是被破坏的点,那么就是0(特判)
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 50000 + 10;
int const inf = 0x7f7f7f7f;
int n,m,last[N],tot;
struct Node
{
int l,r,maxd,mind;
}node[N<<2];
void build(int id,int l,int r){
node[id].l = l,node[id].r = r;
if(l == r){
node[id].maxd = 0, node[id].mind = n+1;
}else{
int mid = (l + r) >> 1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
node[id].maxd = max(node[id<<1].maxd,node[id<<1|1].maxd);
node[id].mind = min(node[id<<1].mind,node[id<<1|1].mind);
}
}
void updata_min(int id,int pos,int k){
int l = node[id].l, r = node[id].r;
if(l == r){
node[id].mind = k;
}else{
int mid = (l + r) >> 1;
if(pos <= mid) updata_min(id<<1,pos,k);
else updata_min(id<<1|1,pos,k);
node[id].mind = min(node[id<<1].mind,node[id<<1|1].mind);
}
}
void updata_max(int id,int pos,int k){
int l = node[id].l, r = node[id].r;
if(l == r){
node[id].maxd = k;
}else{
int mid = (l + r) >> 1;
if(pos <= mid) updata_max(id<<1,pos,k);
else updata_max(id<<1|1,pos,k);
node[id].maxd = max(node[id<<1].maxd,node[id<<1|1].maxd);
}
}
int query_max(int id,int L,int R){
int l = node[id].l, r = node[id].r;
if(L <= l && r <= R){
return node[id].maxd;
}else{
int mid = (l + r) >> 1;
int maxd = 0;
if(L <= mid) maxd = max(maxd,query_max(id<<1,L,R));
if(mid < R) maxd = max(maxd,query_max(id<<1|1,L,R));
return maxd;
}
}
int query_min(int id,int L,int R){
int l = node[id].l, r = node[id].r;
if(L <= l && r <= R){
return node[id].mind;
}else{
int mid = (l + r) >> 1;
int mind = inf;
if(L <= mid) mind = min(mind,query_min(id<<1,L,R));
if(mid < R) mind = min(mind,query_min(id<<1|1,L,R));
return mind;
}
}
int main(){
while(~ scanf("%d%d",&n,&m)){
tot = 0;
build(1,1,n);
for(int i=1;i<=m;i++){
char c;
int x;
scanf(" %c",&c);
if(c == 'D'){
scanf("%d",&x);
last[++tot] = x;
updata_min(1,x,x); //x位置变成x本身
updata_max(1,x,x);
}else if(c == 'Q'){
scanf("%d",&x);
int mind = query_min(1,x,n); //询问[x,n]的最小值
int maxd = query_max(1,1,x); //询问[1,x]的最大值
if(mind == maxd) printf("%d\n",0);
else printf("%d\n",mind-maxd-1);
}else{
int tmp = last[tot--];
updata_min(1,tmp,n+1);
updata_max(1,tmp,0);
}
}
}
return 0;
}