hdu4302

来源:互联网 发布:java 接口 调用接口 编辑:程序博客网 时间:2024/06/18 11:26
/*
分析:
    线段树(其它方法也行)。
    除了最低的一级节点储存该节点有几个cake,其它的节点
表示其所代表的区间内有没有cake。
    有一点真心不明白了,为什么一定要开6倍的空间(60W)才
过,否则就数组越界,线段树开4倍的节点不就妥妥的够了么?
难道我理解有问题?还请路过的牛牛随手给个解释,谢了~


                                                   2012-12-11
*/










#include"stdio.h"#include"string.h"#include"stdlib.h"#include"math.h"#define N 100011int n,m;struct Segtree{int l,mid,r;int flag;}T[6*N];void build(int l,int r,int k){T[k].l=l;T[k].r=r;T[k].mid=(l+r)>>1;T[k].flag=0;if(l==r)return ;build(l,T[k].mid,2*k);build(T[k].mid+1,r,2*k+1);}void update(int aim,int dir,int k){if(T[k].l==T[k].r && T[k].l==aim){T[k].flag+=dir;return ;}if(aim<=T[k].mid)update(aim,dir,2*k);elseupdate(aim,dir,2*k+1);T[k].flag=T[2*k].flag || T[2*k+1].flag;}int find_l(int l,int r,int k){if(T[k].l==l && T[k].r==r && l==r){if(T[k].flag)return l;elsereturn -1;}int ans=-1;if(r<=T[k].mid && T[2*k].flag)ans=find_l(l,r,2*k);else if(l>T[k].mid && T[2*k+1].flag)ans=find_l(l,r,2*k+1);else{if(T[2*k+1].flag)ans=find_l(T[k].mid+1,r,2*k+1);if(ans==-1 && T[2*k].flag)ans=find_l(l,T[k].mid,2*k);}return ans;}int find_r(int l,int r,int k){if(T[k].l==l && T[k].r==r && l==r){if(T[k].flag)return l;elsereturn -1;}int ans=-1;if(r<=T[k].mid && T[2*k].flag)ans=find_r(l,r,2*k);else if(l>T[k].mid && T[2*k+1].flag)ans=find_r(l,r,2*k+1);else{if(T[2*k].flag)ans=find_r(l,T[k].mid,2*k);if(ans==-1 && T[2*k+1].flag)ans=find_r(T[k].mid+1,r,2*k+1);}return ans;}int main(){int T,Case;int a,b;int pre,dire,sum;scanf("%d",&T);for(Case=1;Case<=T;Case++){scanf("%d%d",&n,&m);build(0,n,1);sum=pre=0;dire=1;int x,temp;while(m--){scanf("%d",&x);if(!x){scanf("%d",&x),update(x,1,1);}else{a=find_l(0,pre,1);b=find_r(pre,n,1);if(a==-1 && b==-1)continue;if(a==-1)temp=b;else if(b==-1)temp=a;else{if(pre-a<b-pre)temp=a;else if(pre-a>b-pre)temp=b;else if(dire==1)temp=b;elsetemp=a;}update(temp,-1,1);if((temp-pre)*dire<0)dire*=-1;sum+=abs(temp-pre);pre=temp;}}printf("Case %d: %d\n",Case,sum);}return 0;}