hdu 1540 Tunnel Warfare(单点更新,区间合并)

来源:互联网 发布:macbook 软件下载 编辑:程序博客网 时间:2024/04/30 15:12

题意:给你n连成一条线的点,m个操作。D x把第x个村庄破坏,Q x查询与第x个村庄直接和间接相连的村庄数目(包括它自己),R把最早破坏的一个村庄恢复。

        除了下面的另一种方法外,现在再做的时候,想到了另一种方法,在查询的时候,更新查找到的范围的左右端点。

/*代码风格更新后*/#include <iostream>#include <cstdio>#include <cstring>#include <stack>using namespace std;#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define MID(a,b) (a+((b-a)>>1))const int N=50005;struct node{int lft,rht;int lmx,rmx;int len(){return rht-lft+1;}int mid(){return MID(lft,rht);}void init(){lmx=rmx=len();}void fun(int valu){if(valu==-1) lmx=rmx=0;else lmx=rmx=1;}};int n,m;struct Segtree{node tree[N*4];void up(int ind){tree[ind].lmx=tree[LL(ind)].lmx;tree[ind].rmx=tree[RR(ind)].rmx;if(tree[LL(ind)].lmx==tree[LL(ind)].len())tree[ind].lmx+=tree[RR(ind)].lmx;if(tree[RR(ind)].rmx==tree[RR(ind)].len())tree[ind].rmx+=tree[LL(ind)].rmx;}void build(int lft,int rht,int ind){tree[ind].lft=lft,tree[ind].rht=rht;tree[ind].init();if(lft!=rht){int mid=tree[ind].mid();build(lft,mid,LL(ind));build(mid+1,rht,RR(ind));}}void updata(int pos,int ind,int valu){if(tree[ind].lft==tree[ind].rht) tree[ind].fun(valu);else{int mid=tree[ind].mid();if(pos<=mid) updata(pos,LL(ind),valu);else updata(pos,RR(ind),valu);up(ind);}}void query(int pos,int ind,int& x,int& y){if(tree[ind].lft==tree[ind].rht){if(tree[ind].lmx==1) x=y=tree[ind].lft;else x=y=0;}else{int mid=tree[ind].mid();if(pos<=mid) query(pos,LL(ind),x,y);else query(pos,RR(ind),x,y);if(tree[LL(ind)].rht==y) y+=tree[RR(ind)].lmx;if(tree[RR(ind)].lft==x) x-=tree[LL(ind)].rmx;}}}seg;int main(){while(scanf("%d%d",&n,&m)!=EOF){stack<int> q;seg.build(1,n,1);while(m--){char cmd[5];int pos,st,ed;scanf("%s",cmd);if(cmd[0]=='D'){scanf("%d",&pos);seg.updata(pos,1,-1);q.push(pos);}else if(cmd[0]=='Q'){scanf("%d",&pos);seg.query(pos,1,st,ed);if(st==0&&ed==0) puts("0");else printf("%d\n",ed-st+1);//cout<<st<<" "<<ed<<endl;}else{seg.updata(q.top(),1,1);                q.pop();}}}return 0;}


        题目没有说有多组数据,不过却有多组数据,晕死。和hotel那题比较相似,在查询的时候要注意,要先查询是否在父区间的左端点的和右端点连续的范围内,然后查询是否在左右子区间的连接处。而不是查询是否在左子区间的左端点的连续的范围内,这样会出现错误。因为有一种情况是父区间的连续范围超过了中点。

/*代码风格更新前*/#include <iostream>#include <cstdio>#include <stack>using namespace std;const int N=50005;struct node{    int left,right;    int lmax,rmax;    int mid(){return left+(right-left)/2;}    int dis(){return right-left+1;}};struct Segtree{    node tree[N*4];    void build(int left,int right,int r)    {        tree[r].left=left;  tree[r].right=right;        tree[r].lmax=tree[r].rmax=tree[r].dis();        if(left<right)        {            int mid=tree[r].mid();            build(left,mid,r*2);            build(mid+1,right,r*2+1);        }    }    void updata(int pos,int r,int co)    {        if(tree[r].left==tree[r].right) tree[r].lmax=tree[r].rmax=co;        else        {            int mid=tree[r].mid();            if(pos<=mid) updata(pos,r*2,co);            else if(pos>mid) updata(pos,r*2+1,co);            tree[r].lmax=tree[r*2].lmax;    tree[r].rmax=tree[r*2+1].rmax;            if(tree[r*2].lmax==tree[r*2].dis()) tree[r].lmax+=tree[r*2+1].lmax;            if(tree[r*2+1].rmax==tree[r*2+1].dis()) tree[r].rmax+=tree[r*2].rmax;        }    }    int query(int pos,int r)    {        if(tree[r].left==tree[r].right) return tree[r].lmax;        else        {            int mid=tree[r].mid();            if(tree[r].lmax+tree[r].left>pos) return tree[r].lmax;            else if(tree[r*2+1].lmax+tree[r*2+1].left>pos&&tree[r*2].right-tree[r*2].rmax<pos)return tree[r*2].rmax+tree[r*2+1].lmax;            else if(tree[r].right-tree[r].rmax<pos) return tree[r].rmax;            else if(pos<=mid) return query(pos,r*2);            else return query(pos,r*2+1);        }    }}seg;int main(){    int n,m;    while(scanf("%d%d",&n,&m)!=EOF)    {        stack<int> q;        seg.build(1,n,1);        for(int i=0;i<m;i++)        {            int a;            char cmd[5];            scanf("%s",cmd);            if(cmd[0]=='D')            {                scanf("%d",&a);                seg.updata(a,1,0);                q.push(a);            }            else if(cmd[0]=='Q')            {                scanf("%d",&a);                printf("%d\n",seg.query(a,1));            }            else            {                seg.updata(q.top(),1,1);                q.pop();            }        }    }    return 0;}