SGU 263 Towers(树状数组)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=263

题意:一排位置,开始全为0.若一段区间[L,R]之间均大于0且L-1和R+1均为0,我们说[L,R]为一段。两种改变,四种询问。改变是:(1)将第x个位置增加y;(2)将第t段的第x个位置增加y。四种询问是:(1)段的个数;(2)第t段中的所有数之和;(3)第t段的区间长度;(4)第t段上第x个位置的数是多少。

思路:一开始用splay+并查集WA了半天。最后看别人的BIT+并查集,好犀利。。。



int root[N],num[N],c[N],sum[N],p[N];

int n;



int getRoot(int x)

{

    if(root[x]!=x) root[x]=getRoot(root[x]);

    return root[x];

}



int search(int c[],int x,int y)

{

    int ans=0;

    while(y) ans+=c[y],y-=y&-y;

    x--;

    while(x) ans-=c[x],x-=x&-x;

    return ans;

}



void insert(int c[],int x,int det)

{

    while(x<N) c[x]+=det,x+=x&-x;

}





void Union(int x,int y)

{

    num[x]+=num[y];

    root[y]=x;

}



int getStart(int k)

{

    int low=1,high=N-1,mid,temp;

    while(low<=high)

    {

        mid=(low+high)>>1;

        if(search(c,1,mid)<k) low=mid+1;

        else high=mid-1;

    }

    if(high>=1&&search(c,1,high)==k) return high;

    return low;

}



void putCube(int x,int y)

{

    insert(sum,y,x);

    if(p[y]) return;

    p[y]=1;

    x=getRoot(y-1);

    if(p[x]) Union(x,y);

    else insert(c,y,1);

    if(p[y+1])

    {

        insert(c,y+1,-1);

        x=getRoot(y);

        Union(x,y+1);

    }

}



void put()

{

    int x,c;

    scanf("%d%d",&x,&c);

    putCube(c,x);

}



void tput()

{

    int t,x,c,p;

    scanf("%d%d%d",&t,&x,&c);

    p=getStart(t);

    putCube(c,p+x-1);

}



void towers()

{

    printf("%d towers\n",search(c,1,N-1));

}



void cubes()

{

    int t,p;

    scanf("%d",&t);

    p=getStart(t);

    printf("%d cubes in %dth tower\n", search(sum,p,p+num[p]-1),t);

}



void length()

{

    int t,p;

    scanf("%d",&t);

    p=getStart(t);

    printf("length of %dth tower is %d\n",t,num[p]);

}



void tcubes()

{

    int t,x,p;

    scanf("%d%d",&t,&x);

    p=getStart(t)+x-1;

    printf("%d cubes in %dth column of %dth tower\n",search(sum,p,p),x,t);

}



int main()

{

    int i;

    for(i=0;i<N;i++) num[i]=1,root[i]=i;

    scanf("%d",&n);

    char cmd[15];

    while(n--)

    {

        scanf("%s",cmd);

        if(cmd[0]=='p') put();

        else if(cmd[0]=='t'&&cmd[1]=='p') tput();

        else if(cmd[0]=='t'&&cmd[1]=='o') towers();

        else if(cmd[0]=='c') cubes();

        else if(cmd[0]=='l') length();

        else if(cmd[0]=='t'&&cmd[1]=='c') tcubes();

    }

}

  

你可能感兴趣的:(树状数组)