题目链接: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); } } } }