HDU 4441 【Splay】 Queue Sequence

来源:互联网 发布:怎样学好粤语知乎 编辑:程序博客网 时间:2024/05/06 08:40
/**Rainto96*Beijing University of Posts and Telecommunications School of SoftwareEngineering*http://blog.csdn.net/u011775691http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96673#problem/K题目需要维护三个操作1.在位置p插入一个序列中没有出现过的最小的正整数,同时将它的相反数插入合乎队列性质的最右边的位置2.删除数p和-p3.查询p和-p之间的数的和是多少此题我卡了很久,原因如下1.由于有插入到某个位置的操作,实现上一般是插入到某个点后,因此,有必要加入虚点,然后对题目输入的位置和序列位置进行转换。虚点可以大大减少边界判断2.没有insert到某个位置的模板3.没有根据某个节点下标remove这个节点的模板4.val[x] <0 写成 val < 0,编译器没有任何的报错与警告5.在用cxlove的remove模板时候,它维护了树中节点的真正个数tot,然而我的newnode分配下标的变量也是tot,导致我该变量被减,查了很久解法:2操作和3操作都没什么好说的2操作维护数字与节点编号的对应关系就可以3操作维护sum区间和这个信息就可以1操作,首先要知道当前序列中最小的没出现过的正整数,这个可以用segmenttree来维护然后正整数直接插入位置p对于负整数首先要知道p位置左边有多少个正整数,比如为n个那么负整数需要插入到n+1个整数之前,这样可以通过找第n+1个正整数的节点下标即可需要维护区间内正数个数和负数个数的信息*/#include <iostream>#include <cstdio>#include <algorithm>#include <queue>#include <cstring>#include <string>#include <cmath>#include <set>#include <map>#include <vector>#include <climits>using namespace std;#define pb push_back#define ALL(x) x.begin(),x.end()#define VINT vector<int>#define PII pair<int,int>#define MP(x,y) make_pair((x),(y))#define ll long long#define ull unsigned ll#define MEM0(x)  memset(x,0,sizeof(x))#define MEM(x,val) memset((x),val,sizeof(x))#define scan(x) scanf("%d",&(x))#define scan2(x,y) scanf("%d%d",&(x),&(y))#define scan3(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))#define scan4(x,y,z,k) scanf("%d%d%d%d",&(x),&(y),&(z),&(k))#define Max(a,b) a=max(a,b)#define Min(a,b) a=min(a,b)using namespace std;const int N = 201111;int cha[2*N];int ch[N][2];int val[N], pre[N], sz[N], cnt[N][2];ll sum[N];#define lson ch[x][0]#define rson ch[x][1]struct Splay{        int root,tot;        inline void Treaval(int x) {                if(x) {                        Treaval(ch[x][0]);                        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d \n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);                        Treaval(ch[x][1]);                }        }        inline void debug() {printf("%d\n",root);Treaval(root);}        inline void init(){                root= tot =0;val[root] = ch[root][0]=ch[root][1]=pre[root]=sz[root]=sum[0]=cnt[0][0]=cnt[0][1]=0;  ///                root = newnode(0,0);                ch[root][1] = newnode(0,root);                pushup(ch[root][1]);                pushup(root);        }        inline int newnode(int value, int fa){                int k = ++tot;                pre[k] = fa;                ch[k][0] = ch[k][1] = 0;                sz[k] = 1;                val[k] = value;                sum[k] = value;                cnt[k][0] = value > 0;                cnt[k][1] = value < 0;                if(k>N) k/=0;                return k;        }        inline void pushup(int x){                if(x==0) return;                sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1;                sum[x] = sum[lson] + sum[rson] + val[x];                cnt[x][0] = cnt[lson][0] + cnt[rson][0] + (val[x] > 0);///////!!!!!!!这里写错了写成val > 0,愣是没报错没warning                cnt[x][1] = cnt[lson][1] + cnt[rson][1] + (val[x] < 0);        }        inline void rotate(int x,int kind){            int y=pre[x];            ch[y][!kind]=ch[x][kind];            pre[ch[x][kind]]=y;            if(pre[y])                ch[pre[y]][ch[pre[y]][1]==y]=x;            pre[x]=pre[y];            ch[x][kind]=y;            pre[y]=x;            pushup(y);        }        inline void splay(int r,int goal){            while(pre[r]!=goal){                if(pre[pre[r]]==goal)                    rotate(r,ch[pre[r]][0]==r);                else{                    int y=pre[r];                    int kind=(ch[pre[y]][0]==y);                    if(ch[y][kind]==r){                        rotate(r,!kind);                        rotate(r,kind);                    }                    else{                        rotate(y,kind);                        rotate(r,kind);                    }                }            }            pushup(r);            if(goal==0) root=r;        }        inline void rotateTo(int k, int goal) {            int x=root;            while(k!=sz[ch[x][0]]+1){                if (k<=sz[ch[x][0]]){                    x=ch[x][0];                }else{                    k-=(sz[ch[x][0]]+1);                    x=ch[x][1];                }            }            splay(x,goal);        }        inline void remove(int r){            splay(r,0);            int pos=sz[ch[r][0]];            rotateTo(pos,0);            rotateTo(pos+2,root);            #define Key_value ch[ch[root][1]][0]            Key_value=0;            pushup(ch[root][1]);            pushup(root);        }        inline int insert(int pos,int value){                rotateTo(pos, 0);                rotateTo(pos+1, root);                int k = newnode(value,ch[root][1]);                ch[ch[root][1]][0] = k;                pushup(ch[root][1]);                pushup(root);                return k;        }        inline int find(int x,int n){                int l = ch[x][0], r= ch[x][1];                if(cnt[l][1] == n && val[x] < 0){                        splay(x,0);return sz[ch[root][0]];                }else if(cnt[l][1]>=n+1) return find(l,n);                else return find(r, n-cnt[l][1] - (val[x]<0) );        }}spl;#undef lson#undef rson#define lson (x)<<1#define rson (x)<<1|1struct Node{        int l,r,val,fir;};struct Seg{        Node node[N*4];        inline void pushup(int x){                node[x].fir = min(node[lson].fir , node[rson].fir);        }        inline void build(int l,int r,int x=1){                node[x].l = l ,node[x].r= r;node[x].val = 0;node[x].fir = l;                if(l==r){                        return;                }                int mid = (l+r)/2;                build(l,mid,lson);                build(mid+1,r,rson);                pushup(x);        }        inline void update(int v, int val, int x=1){                if(node[x].l == node[x].r){                        node[x].val = val;                        if(node[x].val == 0) node[x].fir = node[x].l;                        else node[x].fir = 0x3f3f3f3f;                        return;                }                int mid = (node[x].l + node[x].r)/2;                if(v <= mid) update(v, val, lson);                if(v > mid) update(v,val,rson);                pushup(x);        }}seg;int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);        int Q;        int Cas = 1;        while(scan(Q) == 1){                printf("Case #%d:\n",Cas++);                char op[66];                int p;                seg.build(1,Q+10);                spl.init();                for(int i=0;i<Q;i++){                        scanf("%s%d",op,&p);                        if(op[0]=='i'){                                int num = seg.node[1].fir;                                cha[num+N] = spl.insert(p+1,num);                                spl.splay(cha[num+N], 0);                                int n = cnt[ch[spl.root][0]][0];                                if(cnt[spl.root][1] <= n){                                        int m = sz[spl.root] - 2 + 1;                                        cha[-num+N] = spl.insert(m,-num);                                }else{                                        int m = spl.find(spl.root,n);//某点左边有n个负数且这个点为负数                                        cha[-num+N] = spl.insert(m,-num);                                }                                seg.update(num,1);                        }else if(op[0]=='q'){                                int id1 = cha[p+N];                                int id2 = cha[-p+N];                                spl.splay(id1,0);                                spl.splay(id2,spl.root);                                printf("%I64d\n",sum[ch[ch[spl.root][1]][0]]);                        }else if(op[0]=='r'){                                int id1 = cha[p+N];                                int id2 = cha[-p+N];                                spl.remove(id1);                                spl.remove(id2);                                seg.update(p,0);                        }                }        }}

0 0