poj 2352 treap

题意:先按Y的升序然后再按X的升序给出坐标,求出每个坐标左下方有多少个点,最后输出有从0到n-1个点的坐标有多少个。

分析:本题可以看成是 树状数组的入门题,但是用treap同样也可以解决。由于坐标是按照y递增的顺序输入。所以不需要记录、处理y坐标,对x坐标维护一个treap,对每个节点维护一个总节点数sum。 虽然没有完全相同的两个点,但是x坐标可以相同,所以储存一个当前节点的个数val,最后计算的时候这是要考略的,由于忽略这个WA了三次。

简单的treap,每次插入一个x,然后查询小于等于它的节点的个数就行了。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;
struct node
{
    int r,v,sum,val;
    node* ch[2];
    node (int v):v(v){ch[0] = ch[1] = NULL; r = rand(); sum = 1; val = 1;}
    bool operator <(const node &a) const
    {
        return r <a.r;
    }
    int cmp(int x)
    {
        if(v == x) return -1;
        return x < v ? 0 : 1;
    }
};
node *root;
void pushup(node* &o)
{
        o->sum = o->val;
    if(o->ch[0] != NULL) o->sum += o->ch[0]->sum;
    if(o->ch[1] != NULL) o->sum += o->ch[1]->sum;
}
void rotate(node* &o, int d)
{
    node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d];k ->ch[d] = o;
    pushup(o);
    pushup(k);
    if(o == root) root = k;
    o = k;
}
void insert(node* &o, int x)
{
    if(o == NULL) o = new node(x);
    else
    {
        int d = o->cmp(x);
        if(d == -1)
        {
            o->val ++;
            o->sum ++;
        }
        else
        {
         insert(o->ch[d],x);
         pushup(o);
         if(o->ch[d]->r > o->r) rotate(o,d^1);
        }
    }
}
int find(node* &o, int x)
{
    //cout << o->v <<"    " << x << endl;
    int ans = 0;
    int d = o->cmp(x);
    if(d == -1)
    {
        ans += o->val - 1;
        if(o->ch[0] != NULL) ans += o->ch[0]->sum;
        return ans;
    }
    else
    {
        if(d == 1) ans += o->val;
        if(d == 1 && o->ch[0] != NULL) ans += o->ch[0]->sum;
        return ans += find(o->ch[d],x);
    }
}
int ans[15000+ 5];
int main()
{
      int n;
      while(~scanf("%d",&n))
      {
          root = NULL;
          memset(ans,0,sizeof(ans));
          for(int i = 1; i <= n; i++)
          {
              int x,y; scanf("%d %d",&x,&y);
              insert(root,x);
               int pos = find(root,x);
               //cout << pos << endl;
               ans[pos] ++;
          }
          for(int i = 0; i < n; i ++)
          {
              printf("%d\n",ans[i]);
          }
      }
}


猜你喜欢

转载自blog.csdn.net/zlatan10/article/details/77116192