hdu 4302 Holedox Eating 线段树去维护蛋糕!! 多校联合赛第三题

来源:互联网 发布:淘宝基础题 编辑:程序博客网 时间:2024/05/16 13:47

好囧啊!!打完貌似很快可调试一整天,太伤了,要是没有驴薛的对拍程序,我估计要整的没完没了,吐血了!!

不知到怎么想的,上来就想吃完蛋糕在走道,可题意分明是先找到蛋糕再吃!!貌似大家都不知道我在说什么,小小的吐曹一下!!

总之,思路不清晰千万不开始打代码!!!后换无穷啊!!!!!


#include<iostream>#include<cstdio>using namespace std;#define max1 100005#define inf 0xFFFFFFstruct node{    int l,r,ml,mr,cnt;//ml是这个线段的最左面的蛋糕,mr是这个线段最右面的蛋糕}a[max1*5];int x,y,s,sign1;int ab(int x){//计算绝对值    if(x<0) return x*(-1);    return x;}void build(int left,int right ,int i){    a[i].cnt=0;//记录线段里蛋糕的个数    a[i].l=left;    a[i].r=right;    a[i].ml=inf;//初始化左面是最大的,右面最小的    a[i].mr=(-1)*inf;    if(a[i].l==a[i].r) return ;    int mid=(left+right)>>1;    build(left,mid,2*i);    build(mid+1,right,2*i+1);}void insert(int k,int i){    if(a[i].ml>k) a[i].ml=k;    if(a[i].mr<k) a[i].mr=k;    a[i].cnt++;    if(a[i].l==a[i].r) return ;    int mid=(a[i].l+a[i].r)>>1;    if(k<=mid) insert(k,i*2);    else insert(k,i*2+1);}void delete_num(int k,int i){    if(a[i].cnt!=0)    a[i].cnt--;    if(a[i].l==a[i].r){            if(a[i].cnt==0) {//如果最后一个线段的没有点了,就将其线段的表上初始值                a[i].ml=inf;                a[i].mr=(-1)*inf;            }            return ;    }    int mid=(a[i].l+a[i].r)>>1;    if(k<=mid) delete_num(k,i*2);    else delete_num(k,i*2+1);    a[i].ml=a[i*2].ml<a[i*2+1].ml ? a[i*2].ml:a[i*2+1].ml;//更新父亲节点区左右孩子的ml的最大值    a[i].mr=a[i*2].mr>a[i*2+1].mr ? a[i*2].mr:a[i*2+1].mr;//更新父亲节点区左右孩子的mr的最校值}void querry(int k,int i){    int mid=(a[i].l+a[i].r)>>1;    if(a[i].l==a[i].r){        if(a[i].cnt>=1) sign1=1;//标记是否这个点还有蛋糕,如果a[i].cnt>=1,则要原地不动        return ;    }    if(k<=mid){        if(a[i*2+1].cnt)            y=a[i*2+1].ml;//向左移动的时取右面线段的最左面的蛋糕        querry(k,i*2);    }    else{        if(a[i*2].cnt)            x=a[i*2].mr;//向右移动的时取左面线段的最右面的蛋糕        querry(k,i*2+1);    }}int main(){    int n,q,p,k,l,pp=1;    scanf("%d",&n);    while(n--){        int sign;//标记方向        s=0;        long long sum=0;//注意L可以为100000,次数也可一100000,也就是说sum可以达到10^10        scanf("%d%d",&q,&p);        build(0,q+1,1);        while(p--){            scanf("%d",&k);            if(k==0){                scanf("%d",&l);                insert(l,1);            }            else{                sign1=0;                x=inf;y=(-1)*inf;                querry(s,1);                if(sign1==1){//如果自己所在的点就有蛋糕的话就不用移动啦!!直接删除就可一                    delete_num(s,1);                    continue;                }                if(x==inf && y==inf*(-1))//防止你一直输入1,都没有蛋糕啦                    continue;                int ta=ab(x-s);                int te=ab(y-s);                if(ta>te){                    s=y;sum+=te;sign=1;                }                else if(ta<te){                    s=x;sum+=ta;sign=0;                }                else{                    if(sign==0) {                        s=x;sum+=ta;                    }                    if(sign==1) {                        s=y;sum+=te;                    }                }                delete_num(s,1);            }        }        printf("Case %d: ",pp++);        cout<<sum<<endl;    }}