题目链接:http://poj.org/problem?id=2892
题目大意:求与一个点连通的点数,即包含x的区间连续为1的长度。
题目思路:我的做法是直接查(1,x)的右连续(大于0)+(x+1)的左连续,还有一种做法是直接查连续长度,需要讨论点在区间的位置。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define M 110000
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int q[M];
struct node
{
int l,lnum,r,rnum;
int mid()
{
return (l+r)>>1;
}
}T[4*M];
void up(int rt)
{
T[rt].lnum=T[rt<<1].lnum;
T[rt].rnum=T[rt<<1|1].rnum;
if(T[rt<<1].lnum==T[rt<<1].r-T[rt<<1].l+1)
T[rt].lnum+=T[rt<<1|1].lnum;
if(T[rt<<1|1].rnum==T[rt<<1|1].r-T[rt<<1|1].l+1)
T[rt].rnum+=T[rt<<1].rnum;
}
int query(int l,int r,int rt,int tp)
{
if(T[rt].l==l&&T[rt].r==r)
{
if(tp==0)
return T[rt].lnum;
else
return T[rt].rnum;
}
int mid=T[rt].mid();
if(r<=mid)
return query(l,r,rt<<1,tp);
else if(l>mid)
return query(l,r,rt<<1|1,tp);
else
{
int a;
if(tp==0)
{
a=query(l,mid,rt<<1,tp);
if(a==mid-l+1)
a+=query(mid+1,r,rt<<1|1,tp);
}
else
{
a=query(mid+1,r,rt<<1|1,tp);
if(a==r-mid)
a+=query(l,mid,rt<<1,tp);
}
return a;
}
}
void build(int l,int r,int rt)
{
T[rt].l=l;T[rt].r=r;
if(l==r)
{
T[rt].lnum=T[rt].rnum=1;
return;
}
int mid=T[rt].mid();
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
up(rt);
}
void modify(int x,int rt,int data)
{
if(T[rt].l==T[rt].r)
{
T[rt].lnum=T[rt].rnum=data;
return;
}
int mid=T[rt].mid();
if(x<=mid)
modify(x,rt<<1,data);
else
modify(x,rt<<1|1,data);
up(rt);
}
int main()
{
char op[10];
int n,m,i,x;
while(scanf("%d%d",&n,&m)!=EOF)
{
int top,tail;
top=tail=0;
build(1,n,1);
for(i=0;i<m;i++)
{
scanf("%s",op);
if(op[0]=='D')
{
scanf("%d",&x);
modify(x,1,0);
q[tail++]=x;
}
else if(op[0]=='R')
{
if(top<tail)
{
modify(q[tail-1],1,1);
tail--;
}
}
else
{
scanf("%d",&x);
int rec=query(1,x,1,1);
if(rec==0)
{
printf("0\n");
continue;
}
else
{
if(x+1<=n)
rec+=query(x+1,n,1,0);
}
printf("%d\n",rec);
}
}
}
}