Splay(hdu4441Queue Sequence)好题

来源:互联网 发布:校园网络建设招标书 编辑:程序博客网 时间:2024/06/11 02:48

Queue Sequence

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1412    Accepted Submission(s): 356


Problem Description
There's a queue obeying the first in first out rule. Each time you can either push a number into the queue (+i), or pop a number out from the queue (-i). After a series of operation, you get a sequence (e.g. +1 -1 +2 +4 -2 -4). We call this sequence a queue sequence.

Now you are given a queue sequence and asked to perform several operations:

1. insert p
First you should find the smallest positive number (e.g. i) that does not appear in the current queue sequence, then you are asked to insert the +i at position p (position starts from 0). For -i, insert it into the right most position that result in a valid queue sequence (i.e. when encountered with element -x, the front of the queue should be exactly x).
For example, (+1 -1 +3 +4 -3 -4) would become (+1 +2 -1 +3 +4 -2 -3 -4) after operation 'insert 1'.
2. remove i
Remove +i and -i from the sequence.
For example, (+1 +2 -1 +3 +4 -2 -3 -4) would become (+1 +2 -1 +4 -2 -4) after operation 'remove 3'.
3. query i
Output the sum of elements between +i and -i. For example, the result of query 1, query 2, query 4 in sequence (+1 +2 -1 +4 -2 -4) is 2, 3(obtained by -1 + 4), -2 correspond.
 

Input
There are less than 25 test cases. Each case begins with a number indicating the number of operations n (1 ≤ n ≤ 100000). The following n lines with be 'insert p', 'remove i' or 'query i'(0 ≤ p ≤ length (current sequence), 1 ≤ i, i is granted to be in the sequence).
In each case, the sequence is empty initially.
The input is terminated by EOF.
 

Output
Before each case, print a line "Case #d:" indicating the id of the test case.
After each operation, output the sum of elements between +i and -i.
 

Sample Input
10insert 0insert 1query 1query 2insert 2query 2remove 1remove 2insert 2query 36insert 0insert 0remove 2query 1insert 1query 2
 

Sample Output
Case #1:2-120Case #2:0-1
 

Source


题目支持三种操作:

insert pos, 把x(x为可用的最小的数)插入对应位置,-x插入对应位置,如1 2 -1 -2 ,3要插入2后面,-3插入-2后面,而求尽量靠右

remove x,把x,-x移除

query x询问x与-x之间的数的和

position数组保存x对应的伸展树中的编号,线段树维护最小的可用的数

insert操作插入x的时候比较好操作,-x的时候,因为要保持顺序,所以x前面有多少个正数,-x前面就有多少个负数,又因为尽力量靠右,所以也就是第n+1个负数的左边

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;#define Key_value ch[ch[root][1]][0]const int maxn=200010;const int INF=1000000000;typedef long long LL;int M;int ch[maxn][2],size[maxn],pre[maxn],cnt[maxn][2],key[maxn];LL sum[maxn];int position[maxn][2];int root,tot1,tot2;set<int> sp;void NewNode(int &r,int f,int val){    r=++tot1;    ch[r][0]=ch[r][1]=0;    cnt[r][0]=val>0;    cnt[r][1]=val<0;    sum[r]=val;    pre[r]=f;    size[r]=1;    key[r]=val;}void pushup(int r){    if(!r)return;    int lson=ch[r][0],rson=ch[r][1];    size[r]=size[lson]+size[rson]+1;    sum[r]=sum[lson]+sum[rson]+key[r];    cnt[r][0]=cnt[lson][0]+cnt[rson][0]+(key[r]>0);    cnt[r][1]=cnt[lson][1]+cnt[rson][1]+(key[r]<0);}void init(){    root=tot1=tot2=0;    ch[root][0]=ch[root][1]=pre[root]=cnt[root][0]=cnt[root][1]=key[root]=size[root]=0;    NewNode(root,0,0);    NewNode(ch[root][1],root,0);    pushup(ch[root][1]);    pushup(root);   // cout<<size[root]<<"***"<<endl;}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);}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;}int get_kth(int r,int k){    int t=size[ch[r][0]]+1;    if(t==k)return r;    if(t>k)return get_kth(ch[r][0],k);    return get_kth(ch[r][1],k-t);}int find(int r,int k){    int lson=ch[r][0],rson=ch[r][1];    if(cnt[lson][1]==k&&key[r]<0)    {        Splay(r,0);        return size[ch[root][0]];    }    else if(cnt[lson][1]>=k+1)return find(lson,k);    else return find(rson,k-cnt[lson][1]-(key[r]<0));}struct InterValTree{    int minv[maxn<<2];    void build(int o,int l,int r)    {        minv[o]=0;        if(l==r)        {            minv[o]=l;            return;        }        int mid=(l+r)>>1;        build(o<<1,l,mid);        build(o<<1|1,mid+1,r);        push_up(o);    }    void push_up(int o)    {        minv[o]=min(minv[o<<1],minv[o<<1|1]);    }    void update(int o,int l,int r,int pos,int flag)    {        if(l==r)        {            if(flag)minv[o]=INF;            else minv[o]=l;            return;        }        int mid=(l+r)>>1;        if(pos<=mid)update(o<<1,l,mid,pos,flag);        else update(o<<1|1,mid+1,r,pos,flag);        push_up(o);    }}tree;void debug(int r){    if(!r)return;    debug(ch[r][0]);    printf("%d ",key[r]);    debug(ch[r][1]);}void Insert(int pos){    int num=tree.minv[1];    tree.update(1,1,M,num,1);    Splay(get_kth(root,pos+1),0);    Splay(get_kth(root,pos+2),root);    NewNode(Key_value,ch[root][1],num);    position[num][0]=Key_value;    pushup(ch[root][1]);    pushup(root);    Splay(Key_value,0);    int n=cnt[ch[root][0]][0];    if(cnt[root][1]<=n)    {        int m=size[root]-2+1;        Splay(get_kth(root,m),0);        Splay(get_kth(root,m+1),root);        NewNode(Key_value,ch[root][1],-num);        position[num][1]=Key_value;    }    else    {        int m=find(root,n);        Splay(get_kth(root,m),0);        Splay(get_kth(root,m+1),root);        NewNode(Key_value,ch[root][1],-num);        position[num][1]=Key_value;    }    pushup(ch[root][1]);    pushup(root);}void Delete(int x){    Splay(x,0);    int pos=size[ch[x][0]];    Splay(get_kth(root,pos),0);    Splay(get_kth(root,pos+2),root);    pre[Key_value]=0;    Key_value=0;    pushup(ch[root][1]);    pushup(root);}void Remove(int x){    Delete(position[x][0]);    Delete(position[x][1]);    tree.update(1,1,M,x,0);}void Query(int x){    Splay(position[x][0],0);    Splay(position[x][1],position[x][0]);    cout<<sum[Key_value]<<endl;;}int main(){    char op[10];    int cas=1;    while(scanf("%d",&M)!=EOF)    {        tree.build(1,1,M);        init();        printf("Case #%d:\n",cas++);        for(int i=1;i<=M;i++)        {            int x;            scanf("%s%d",op,&x);            if(op[0]=='i')Insert(x);            else if(op[0]=='r')Remove(x);            else if(op[0]=='q')Query(x);        }    }    return 0;}




0 0